/* ============================================================
   DUSK — Task Journal  |  Purple Gothic v5
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600;700&family=Cormorant:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600&family=Cormorant+SC:wght@400;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

/* ===== GOTHIC PURPLE PALETTE ===== */
:root {
    --bg-page:         #03010a;
    --bg-app:          rgba(5, 2, 20, 0.87);
    --bg-input:        rgba(8, 3, 30, 0.94);
    --bg-item:         rgba(7, 2, 22, 0.80);
    --bg-item-hover:   rgba(18, 6, 52, 0.93);
    --bg-item-checked: rgba(4, 1, 14, 0.72);
    --bg-toolbar:      rgba(5, 2, 18, 0.92);
    --bg-modal:        rgba(6, 2, 22, 0.98);
    --bg-overlay:      rgba(1, 0, 8, 0.86);
    --bg-extra:        rgba(5, 2, 20, 0.92);
    --bg-group-header: rgba(9, 3, 28, 0.90);
    --bg-tag:          rgba(28, 8, 72, 0.68);

    /* ---- text — --text-muted raised to #9068c0 (≈4.6:1 contrast, WCAG AA) ---- */
    --text-primary:    #f0e8ff;
    --text-secondary:  #b880e8;
    --text-muted:      #9068c0;
    --text-link:       #c090ff;

    --border:          rgba(88, 30, 160, 0.32);
    --border-mid:      rgba(130, 50, 220, 0.48);
    --border-bright:   rgba(170, 90, 255, 0.68);
    --border-input:    rgba(100, 35, 170, 0.40);

    --accent:          #a060ff;
    --accent-soft:     rgba(110, 30, 210, 0.20);
    --accent-hover:    #c898ff;
    --grim-heading:    #d18bff;   /* note titles + body headings — vivid, brighter than bold */
    --accent-glow:     rgba(150, 70, 255, 0.30);
    --accent-dim:      rgba(110, 30, 210, 0.10);

    /* Priority: kept as traffic-light; only checked state goes purple */
    --prio-high:        #e03060;
    --prio-high-bg:     rgba(120, 5, 35, 0.40);
    --prio-high-border: rgba(220, 30, 70, 0.50);
    --prio-medium:      #d09020;
    --prio-medium-bg:   rgba(110, 55, 5, 0.38);
    --prio-medium-border: rgba(210, 120, 20, 0.50);
    --prio-low:         #3cc870;
    --prio-low-bg:      rgba(5, 90, 30, 0.28);
    --prio-low-border:  rgba(30, 180, 70, 0.48);

    /* Checked checkbox → violet/purple */
    --check-done-bg:     linear-gradient(135deg, #7030d0, #a060ff);
    --check-done-border: rgba(160, 80, 255, 0.72);
    --check-done-glow:   rgba(140, 60, 255, 0.40);

    /* deadline-ok is never rendered as a badge (status=null for ok tasks)
       — kept as a token for completeness but mapped to a palette-consistent
       cool-blue instead of the jarring green that was here before (audit C-1) */
    --deadline-ok:         #6688cc;
    --deadline-ok-bg:      rgba(30, 40, 120, 0.28);
    --deadline-warn:       #8080ee;
    --deadline-warn-bg:    rgba(20, 20, 120, 0.40);
    --deadline-urgent:     #d09020;
    --deadline-urgent-bg:  rgba(110, 55, 5, 0.38);
    --deadline-critical:   #e03060;
    --deadline-critical-bg:rgba(120, 5, 35, 0.40);
    --deadline-over:       #a01525;
    --deadline-over-bg:    rgba(90, 0, 18, 0.52);

    --radius-xs: 3px;
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
    --radius-xl: 20px;

    --transition:      0.15s ease;
    --transition-slow: 0.3s cubic-bezier(0.4,0,0.2,1);

    --font-main:  'Cormorant', Georgia, serif;
    --font-title: 'Cinzel', serif;
    --font-label: 'Cormorant SC', serif;
    --font-mono:  'JetBrains Mono', monospace;

    --shadow-sm:   0 2px 10px rgba(0,0,0,0.65);
    --shadow-md:   0 6px 28px rgba(0,0,0,0.78);
    --shadow-lg:   0 16px 60px rgba(0,0,0,0.92), 0 0 40px rgba(70,0,160,0.18);
    --shadow-glow: 0 0 0 1px var(--accent-glow), 0 0 22px var(--accent-glow);
    --shadow-purple: 0 0 25px rgba(120,40,240,0.22);

    /* ── Gothic Motion Token System (audit D-1) ──────────────────
       Named by semantic role, not numeric duration, so each value
       can be tuned globally without hunting scattered magic numbers.

       Easings:
         --ease-gothic   stone-weight: slow start, heavy presence
         --ease-spring   ritual-snap: slight overshoot on settle
         --ease-emerge   veil-lift: smooth, unhurried materialisation
         --ease-sink     burial: accelerates into disappearance

       Durations (rough ladder):
         --dur-micro     immediate feedback (ripples, flickers)
         --dur-quick     fast UI response (hover state, check)
         --dur-standard  normal transitions (modal in/out, toast)
         --dur-ritual    ceremony moments (cycle-complete, allDone)
         --dur-ambient   background atmosphere (appGlow, emblemPulse)
    ──────────────────────────────────────────────────────────── */
    --ease-gothic:   cubic-bezier(0.16, 1, 0.3, 1);
    --ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1);
    --ease-emerge:   cubic-bezier(0.22, 1, 0.36, 1);
    --ease-sink:     cubic-bezier(0.55, 0, 1, 0.45);

    --dur-micro:     80ms;
    --dur-quick:     220ms;
    --dur-standard:  340ms;
    --dur-collapse:  280ms;   /* S1-6/U-3: one tempo for every collapse/expand section */
    --dur-ritual:    520ms;
    --dur-ambient:   6000ms;
}

/* ===== RESET ===== */
*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; }

/* ===== ACCESSIBILITY ===== */

/* Gothic focus ring — keyboard only (:focus-visible), never on mouse/touch.
   Purple glow matches the gothic palette. border-radius:inherit keeps coffin
   checkboxes and pill-buttons looking correct.                               */
:focus-visible {
    outline: 2px solid rgba(180, 100, 255, 0.85);
    outline-offset: 2px;
    border-radius: inherit;
    box-shadow: 0 0 0 4px rgba(140, 60, 255, 0.20), 0 0 12px rgba(160, 80, 255, 0.15);
}
/* Inputs already show a border-color focus state — suppress the duplicate ring.
   Must kill the box-shadow too: text inputs match :focus-visible even on a
   mouse click, and its 4px-spread glow bled past the input's right edge and
   drew a rounded outline over the add-button's left edge. */
input:focus-visible,
textarea:focus-visible,
select:focus-visible { outline: none; box-shadow: none; }

/* P6: search-box is inside .search-wrap which gets its own border highlight —
   never show a focus ring on the input itself to avoid inner rounded glow     */
#search-box:focus-visible { outline: none; box-shadow: none; }

/* Reveal task actions when any child receives keyboard focus                 */
.task-item:focus-within .task-actions { opacity: 1; }

/* Visually hidden but accessible to screen readers                           */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
}
/* Live-region for screen-reader announcements (populated by JS announce())   */
#live-region {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
}

/* Global numeric rendering fix:
   IM Fell English defaults to old-style (descending) numerals.
   font-variant-numeric: lining-nums forces all digits to sit on the baseline.
   tabular-nums gives consistent column width (important in counters/deadlines).
   Cinzel Decorative is caps-only so unaffected. JetBrains Mono already has lining digits.  */
*, *::before, *::after {
    font-variant-numeric: lining-nums tabular-nums;
}

/* ===== BACKGROUND ===== */
body {
    font-family: var(--font-main);
    background-color: var(--bg-page);
    color: var(--text-primary);
    min-height: 100vh;
    font-size: 16px;
    line-height: 1.65;
}

/* Background image lives on this FIXED, viewport-sized layer (not on <body> with
   attachment:scroll). On <body> the `cover` was computed against the full scroll
   height, so the photo re-zoomed/cropped whenever content height changed (toggling
   a note open/closed, short Tasks tab, etc.). A fixed inset:0 layer makes `cover`
   resolve against the viewport — stable framing, no crop on content change. This
   also dodges the iOS Safari repaint cost of background-attachment:fixed (PERF-3):
   a fixed pseudo-element with a static background is composited, never re-rastered. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background:
        linear-gradient(180deg,
            rgba(2, 0, 10, 0.70) 0%,
            rgba(3, 0, 14, 0.60) 40%,
            rgba(2, 0, 10, 0.78) 100%),
        radial-gradient(ellipse 90% 70% at 50% -10%, rgba(80, 20, 170, 0.35) 0%, transparent 65%),
        radial-gradient(ellipse 50% 40% at 5% 80%, rgba(60, 15, 130, 0.2) 0%, transparent 60%),
        radial-gradient(ellipse 40% 35% at 95% 60%, rgba(50, 10, 110, 0.15) 0%, transparent 60%),
        url('bg-gothic.jpg') center 18% / cover no-repeat;
}

body::after {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    /* W-9: Consolidated opacity — SVG rect carries the real value (0.016), CSS wrapper is 1.
       Previous: SVG opacity=0.022 × CSS opacity=0.7 = effective 0.0154. Now explicit. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)' opacity='0.016'/%3E%3C/svg%3E");
    opacity: 1;
}

/* ===== LAYOUT ===== */
.container {
    position: relative;
    z-index: 1;
    width: 100%;
    min-height: 100vh;
    padding: 24px 12px 110px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* PERF-2: appGlow refactored — animated glow moved to ::after with opacity-only
   animation (compositor-only, no repaint). Base box-shadow is static. */
@keyframes appGlowPulse {
    0%, 100% { opacity: 0.26; }
    50%       { opacity: 0.48; }
}

.todo-app {
    width: 100%;
    max-width: 780px;
    background: var(--bg-app);
    border-radius: var(--radius-xl);
    padding: 34px 36px 38px;
    border: 1px solid rgba(140, 55, 220, 0.50);
    margin-top: 30px;
    position: relative;
    backdrop-filter: blur(22px);
    -webkit-backdrop-filter: blur(22px);
    /* Static base shadow — no repaint every frame */
    box-shadow:
        var(--shadow-lg),
        0 0 0 1px rgba(130, 50, 240, 0.22),
        inset 0 1px 0 rgba(200, 140, 255, 0.10),
        inset 0 0 75px rgba(65, 5, 145, 0.13),
        0 0 90px rgba(115, 32, 238, 0.12),
        0 0 140px rgba(90, 20, 200, 0.07);
}
/* Animated glow layer — opacity-only, GPU-composited.
   C-2: lives on a dedicated .app-glow child, NOT .todo-app::after — the ::after
   pseudo is already the bottom hairline below, and stacking both on one
   pseudo-element collapsed the glow into a 1px strip and pushed the bottom line
   to the top. Separate element = each role renders correctly. */
.todo-app > .app-glow {
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    pointer-events: none;
    box-shadow:
        0 0 0 1px rgba(150, 65, 225, 0.18),
        inset 0 1px 0 rgba(200, 150, 255, 0.06),
        inset 0 0 60px rgba(60, 8, 140, 0.09),
        0 0 42px rgba(95, 28, 195, 0.09),
        0 0 90px rgba(68, 15, 160, 0.05);
    animation: appGlowPulse var(--dur-ambient) ease-in-out infinite;
    will-change: opacity;
    z-index: -1;
}

/* Honour reduced-motion: keep static glow, kill the infinite pulse */
@media (prefers-reduced-motion: reduce) {
    .todo-app > .app-glow { animation: none; opacity: 0.38; }
}

.todo-app::before {
    content: '';
    position: absolute;
    top: 0; left: 10%; right: 10%;
    height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(150, 60, 255, 0.25) 15%,
        rgba(200, 100, 255, 0.70) 40%,
        rgba(220, 120, 255, 0.90) 50%,
        rgba(200, 100, 255, 0.70) 60%,
        rgba(150, 60, 255, 0.25) 85%,
        transparent 100%);
    pointer-events: none;
}

.todo-app::after {
    content: '';
    position: absolute;
    bottom: 0; left: 20%; right: 20%;
    height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(100, 30, 200, 0.20) 30%,
        rgba(140, 60, 220, 0.40) 50%,
        rgba(100, 30, 200, 0.20) 70%,
        transparent 100%);
    pointer-events: none;
}

/* ===== HEADER ===== */
.app-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 22px;
    margin-bottom: 26px;
    padding-bottom: 24px;
    position: relative;
}

.app-header::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 160px;
    height: 14px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 14'%3E%3Cline x1='0' y1='7' x2='55' y2='7' stroke='rgba(130,50,220,0.35)' stroke-width='0.8'/%3E%3Cline x1='105' y1='7' x2='160' y2='7' stroke='rgba(130,50,220,0.35)' stroke-width='0.8'/%3E%3Cpath d='M64 7 L66 4 L68 7 L66 10 Z' fill='rgba(130,50,220,0.48)'/%3E%3Ccircle cx='80' cy='7' r='2.5' fill='none' stroke='rgba(130,50,220,0.48)' stroke-width='0.8'/%3E%3Ccircle cx='80' cy='7' r='1' fill='rgba(130,50,220,0.55)'/%3E%3Cpath d='M92 7 L94 4 L96 7 L94 10 Z' fill='rgba(130,50,220,0.48)'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    pointer-events: none;
}



/* Gothic coffin logo emblems */
.brand-emblem {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    filter: drop-shadow(0 0 8px rgba(150,60,255,0.35));
    animation: emblemPulse 4.5s ease-in-out infinite;
}
.brand-emblem-r { animation-delay: -2.25s; }
.brand-svg { display: block; width: 30px; height: 36px; }
@keyframes emblemPulse {
    0%, 100% { filter: drop-shadow(0 0 6px rgba(140,50,240,0.28)); opacity: 0.80; }
    50%       { filter: drop-shadow(0 0 16px rgba(190,100,255,0.65)); opacity: 1.0; }
}

.brand-content { text-align: center; }

.brand-name {
    font-family: var(--font-title);
    font-size: 36px;
    font-weight: 700;
    letter-spacing: 8px;
    color: var(--text-primary);
    text-shadow:
        0 0 20px rgba(160, 80, 255, 0.50),
        0 0 50px rgba(140, 60, 255, 0.25),
        0 0 90px rgba(100, 30, 200, 0.15);
    line-height: 1;
}

.brand-tagline {
    font-size: 10.5px;
    letter-spacing: 3px;
    color: var(--text-muted);
    text-transform: uppercase;
    margin-top: 6px;
    font-family: var(--font-label);
    opacity: 0.9;
}

/* ===== PAGE TABS ===== */
.page-nav {
    display: flex;
    gap: 3px;
    background: var(--bg-input);
    border-radius: var(--radius-md);
    padding: 4px;
    margin-bottom: 24px;
    border: 1px solid var(--border);
    backdrop-filter: blur(8px);
}

.nav-tab {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 12px;
    border-radius: calc(var(--radius-md) - 4px);
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-family: var(--font-label);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1px;
    text-transform: uppercase;
}
.nav-tab svg { width: 13px; height: 13px; }
.nav-tab:hover { color: var(--text-secondary); }
.nav-tab.active {
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.30), rgba(80, 15, 180, 0.20));
    color: var(--accent-hover);
    box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.30), 0 0 12px rgba(120, 40, 220, 0.15);
    font-weight: 600;
    text-shadow: 0 0 10px rgba(160, 90, 255, 0.4);
}

.archive-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 15px;
    height: 15px;
    background: transparent;
    color: var(--text-muted);
    font-size: 9.5px;
    font-weight: 600;
    font-family: var(--font-label);
    border: 1px solid var(--border);
    border-radius: 99px;
    padding: 0 4px;
    margin-left: 3px;
    opacity: 0.75;
    letter-spacing: 0;
}

/* ===== PROGRESS ===== */
/* P3 (variant A): vertical stack — tasks header + dominant bar, then secondary subtask bar */
.progress-section {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin-bottom: 20px;
}

/* Header line above the main bar: tag on the left, count on the right */
.progress-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}
/* The main "задачи" label reads as a header — larger than the secondary footnote tag */
.progress-head .counter-tag {
    font-size: 10.5px;
    opacity: 0.9;
    margin-right: 0;
}

/* Main (dominant) bar — full width, thicker, glowing */
.progress-bar-wrap {
    width: 100%;
    height: 4px;
    background: var(--border);
    border-radius: 99px;
    overflow: visible;
    position: relative;
}

.progress-bar-fill {
    height: 100%;
    border-radius: 99px;
    background: linear-gradient(90deg, #7030d0, var(--accent), #c090ff);
    width: 0%;
    transition: width 0.6s cubic-bezier(0.4,0,0.2,1);
    box-shadow: 0 0 8px rgba(160, 80, 255, 0.5);
    position: relative;
}

.progress-bar-fill::after {
    content: '';
    position: absolute;
    right: -1px; top: 50%;
    transform: translateY(-50%);
    width: 4px; height: 4px;
    background: #c898ff;
    border-radius: 50%;
    box-shadow: 0 0 6px 2px rgba(200, 120, 255, 0.7);
}

.progress-label {
    font-family: var(--font-label);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-primary);
    min-width: 44px;
    text-align: right;
    letter-spacing: 1px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
}
.prog-sep { margin: 0 1px; opacity: 0.45; }

/* P3 (variant A): secondary subtask block under the main bar — thin muted full-width
   bar + a right-aligned footnote. Deliberately lighter/thinner than the tasks bar
   so the hierarchy reads at a glance. */
.subtask-progress {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 1px;
}
.progress-sub-wrap {
    width: 100%;
    height: 2px;                          /* thinner than the 4px main bar */
    background: rgba(140, 60, 220, 0.14);
    border-radius: 99px;
    overflow: hidden;
}
.progress-sub-fill {
    height: 100%;
    width: 0%;
    /* muted gradient, no glow — secondary to the main bar */
    background: linear-gradient(90deg, rgba(110, 45, 190, 0.55), rgba(165, 95, 230, 0.62));
    border-radius: 99px;
    transition: width 0.45s cubic-bezier(0.4,0,0.2,1);
}
.subtask-footnote {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0;
    font-family: var(--font-label);
    font-size: 10px;
    font-weight: 500;
    color: var(--text-secondary);
    letter-spacing: 0.6px;
    line-height: 1;
    opacity: 0.85;
}
.subtask-footnote .prog-sep { margin: 0 1px; opacity: 0.5; }

/* Shared label tag before both counters */
.counter-tag {
    font-family: var(--font-label);
    font-size: 8px;
    font-weight: 400;
    letter-spacing: 0.9px;
    text-transform: uppercase;
    color: var(--text-secondary);
    opacity: 0.75;
    margin-right: 6px;
}

/* ===== INPUT SECTION ===== */
/* P-fix: bottom gap under the "Параметры" toggle = its 9px top margin PLUS the keystone
   diamond's ~4px upward protrusion above the plate frame, so the visible top/bottom air
   around the plate reads symmetric (the diamond makes the top reach higher than the frame). */
.input-section { margin-bottom: 11px; }

.row {
    display: flex;
    align-items: center;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-md);
    overflow: hidden;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.row:focus-within {
    border-color: rgba(150, 70, 255, 0.55);
    /* No inner box-shadow — border highlight only (audit p.9) */
}
.row.shake { animation: shake 0.4s ease; }

@keyframes shake {
    0%, 100% { transform: translateX(0) }
    20% { transform: translateX(-5px) }
    40% { transform: translateX(5px) }
    60% { transform: translateX(-3px) }
    80% { transform: translateX(3px) }
}

/* Two-step danger confirm — pulsing red glow while a delete button is "armed".
   (Was referenced by .confirm-armed rules but never defined → no visible pulse.) */
@keyframes dangerPulse {
    from { box-shadow: 0 0 1px rgba(230, 60, 80, 0.0); }
    to   { box-shadow: 0 0 13px rgba(230, 60, 80, 0.60); }
}

#input-box {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    padding: 14px 16px;
    font-family: var(--font-main);
    font-size: 16px;
    color: var(--text-primary);
    font-weight: 400;
}
#input-box::placeholder { color: var(--text-muted); font-style: italic; }

.btn-add {
    width: 46px;
    height: 46px;
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.35), rgba(80, 15, 180, 0.25));
    border: none;
    border-left: 1px solid var(--border-input);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    flex-shrink: 0;
    transition: all var(--transition);
    margin: 0;
}
.btn-add:hover {
    background: linear-gradient(135deg, var(--accent), rgba(150, 60, 255, 0.8));
    color: #fff;
    box-shadow: var(--shadow-glow);
}
.btn-add:active { animation: btnSeal 0.28s cubic-bezier(0.34, 1.56, 0.64, 1); }
.btn-add svg { width: 18px; height: 18px; }

/* ===== EXPAND BUTTON ===== */
/* P4: gothic reliquary-tablet toggle — compact, centred. Engraved double frame,
   corner studs, mirrored filigree filling the side gaps, and a keystone diamond
   that lights up when the params panel is open (replaces the old chevron). */
.btn-expand {
    position: relative;
    display: flex;
    align-items: center;
    gap: 13px;
    width: fit-content;
    margin: 9px auto 0;           /* compact + centred */
    padding: 10px 20px;
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    border: 1px solid var(--border);
    cursor: pointer;
    color: var(--text-muted);
    font-family: var(--font-label);
    font-weight: 600;
    font-size: 11.5px;
    letter-spacing: 2.5px;
    text-transform: uppercase;
    transition: color var(--transition), box-shadow 0.25s ease, border-color var(--transition);
}
/* inner engraved hairline (the "carved" second line) */
.btn-expand::before {
    content: '';
    position: absolute;
    inset: 3px;
    border: 1px solid rgba(130, 50, 220, 0.16);
    border-radius: 3px;
    pointer-events: none;
    transition: border-color var(--transition);
}
.btn-expand:hover { color: var(--accent); border-color: rgba(140, 60, 255, 0.42); box-shadow: 0 0 14px rgba(160, 80, 255, 0.16); }
.btn-expand:hover::before { border-color: rgba(150, 80, 230, 0.32); }

/* corner studs */
.be-stud { position: absolute; width: 3px; height: 3px; background: var(--border-mid); transform: rotate(45deg); opacity: 0.6; transition: all var(--transition); }
.be-stud.tl { left: 6px; top: 6px; }
.be-stud.tr { right: 6px; top: 6px; }
.be-stud.bl { left: 6px; bottom: 6px; }
.be-stud.br { right: 6px; bottom: 6px; }
.btn-expand:hover .be-stud { background: var(--accent); opacity: 0.85; }

/* keystone diamond — open/closed state indicator (replaces the chevron) */
.be-keystone {
    position: absolute;
    top: -3.5px;
    left: 50%;
    transform: translateX(-50%) rotate(45deg);
    width: 6.5px;
    height: 6.5px;
    border: 1px solid var(--border-mid);
    background: linear-gradient(135deg, rgba(150, 100, 220, 0.30), rgba(36, 16, 72, 0.65));
    transition: background 0.3s ease, border-color 0.25s ease, box-shadow 0.3s ease;
}
.btn-expand.open .be-keystone {
    background: linear-gradient(135deg, #b189ef, #7c47c8);
    border-color: rgba(150, 90, 235, 0.7);
    box-shadow: 0 0 5px rgba(150, 90, 235, 0.42);
}

/* mirrored filigree flankers filling the side gaps */
.be-fil { width: 22px; height: 12px; flex-shrink: 0; opacity: 0.6; transition: opacity var(--transition); }
.be-fil-r { transform: scaleX(-1); }
.btn-expand:hover .be-fil { opacity: 0.95; }

.btn-expand .be-label { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
    .be-keystone, .be-fil, .be-stud { transition: none; }
}

/* ===== EXTRA FIELDS ===== */
/* max-height is controlled by JS (toggleExpand) using scrollHeight — no magic
   900px that causes uneven perceived animation speed (audit C-4).
   The CSS transition handles smooth open/close once JS sets the value.        */
.extra-fields {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height var(--dur-collapse) var(--ease-gothic), opacity var(--dur-collapse) var(--ease-gothic);
}
/* .open class still applied by JS, but max-height value is set inline by JS */
.extra-fields.open { opacity: 1; }
/* Problem 1: while an inline dropdown (e.g. the weekly weekday picker) is open,
   drop the clip so the list isn't cut off by the panel's bottom edge. Only ever
   active when the panel is already fully open (max-height:none), so the open/close
   animation is unaffected. */
.extra-fields.dropdown-open { overflow: visible; }

.extra-row { display: flex; gap: 12px; margin-top: 13px; flex-wrap: wrap; }
.field-group { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.field-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 2px;
    font-family: var(--font-label);
}
.field-label .optional { text-transform: none; font-weight: 400; letter-spacing: 0; color: var(--text-muted); }

/* Group select */
.group-select {
    width: 100%;
    padding: 9px 32px 9px 12px;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    cursor: pointer;
    outline: none;
    transition: border-color var(--transition);
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a50a8' stroke-width='2' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 13px;
}
.group-select:focus { border-color: rgba(150, 70, 255, 0.5); }
.group-select option { background: #060218; color: var(--text-primary); }
.opt-new-group { color: var(--accent); font-style: italic; }

/* Priority selector */
.priority-selector { display: flex; gap: 5px; flex-wrap: wrap; }
.prio-btn {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 6px 11px;
    border-radius: 99px;
    border: 1px solid var(--border);
    font-family: var(--font-label);
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition);
    background: var(--bg-input);
    color: var(--text-secondary);
    white-space: nowrap;
    letter-spacing: 1px;
}
.prio-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
/* "Нет" priority — gothic crescent moons flanking the label on both sides */
.prio-none-ic { width: 11px; height: 11px; flex-shrink: 0; opacity: 0.8; margin: 0 -2px; }
/* right-hand crescent is the mirror of the left one (used in prio + group dropdown) */
.none-moon-r { transform: scaleX(-1); }
.prio-btn.prio-low   .prio-dot { background: var(--prio-low);    }
.prio-btn.prio-medium .prio-dot { background: var(--prio-medium); }
.prio-btn.prio-high  .prio-dot { background: var(--prio-high);   }

.prio-btn.prio-low.active    { background: var(--prio-low-bg);    color: var(--prio-low);    border-color: var(--prio-low-border);    box-shadow: 0 0 8px rgba(40, 200, 80, 0.15); }
.prio-btn.prio-medium.active { background: var(--prio-medium-bg); color: var(--prio-medium); border-color: var(--prio-medium-border); box-shadow: 0 0 8px rgba(210, 130, 20, 0.15); }
.prio-btn.prio-high.active   { background: var(--prio-high-bg);   color: var(--prio-high);   border-color: var(--prio-high-border);   box-shadow: 0 0 8px rgba(230, 30, 70, 0.18); }
.prio-btn.prio-none          { color: var(--text-muted); }
.prio-btn.prio-none.active   { background: rgba(80,30,140,0.15); color: var(--text-secondary); border-color: rgba(120,50,200,0.35); }

/* ── Priority grid (params form) ── Item 8 */
.prio-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px;
}
.prio-grid-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-family: var(--font-label);
    font-size: 10.5px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition);
    background: var(--bg-input);
    color: var(--text-secondary);
    letter-spacing: 1.5px;
    white-space: nowrap;
}
/* ── Priority ignition burst ──────────────────────────────────
   Each button has overflow:hidden + a ::after ripple that fires
   on :active, colour-coded per priority level.                  */
.prio-grid-btn { position: relative; overflow: hidden; }
.prio-grid-btn::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    opacity: 0;
    pointer-events: none;
    transform: scale(0.5);
    transition: none;
}
.prio-grid-btn:active::after {
    opacity: 0.32;
    transform: scale(2.5);
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
                opacity   0.35s ease;
}
/* Colour per level */
.prio-grid-btn[data-prio="none"]::after   { background: radial-gradient(circle, rgba(130,60,220,0.7), transparent 70%); }
.prio-grid-btn[data-prio="low"]::after    { background: radial-gradient(circle, rgba(40,200,80,0.7), transparent 70%); }
.prio-grid-btn[data-prio="medium"]::after { background: radial-gradient(circle, rgba(210,140,20,0.7), transparent 70%); }
.prio-grid-btn[data-prio="high"]::after   { background: radial-gradient(circle, rgba(220,40,70,0.7), transparent 70%); }

@media (prefers-reduced-motion: reduce) {
    .prio-grid-btn::after { display: none; }
}

.prio-grid-btn .prio-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.prio-grid-btn.prio-low   .prio-dot { background: var(--prio-low); }
.prio-grid-btn.prio-medium .prio-dot { background: var(--prio-medium); }
.prio-grid-btn.prio-high  .prio-dot { background: var(--prio-high); }
.prio-grid-btn:hover { border-color: var(--border-mid); color: var(--text-primary); }
.prio-grid-btn[data-prio="none"].active   { background: rgba(80,30,140,0.18); color: var(--text-secondary); border-color: rgba(120,50,200,0.38); }
.prio-grid-btn[data-prio="low"].active    { background: var(--prio-low-bg);    color: var(--prio-low);    border-color: var(--prio-low-border); }
.prio-grid-btn[data-prio="medium"].active { background: var(--prio-medium-bg); color: var(--prio-medium); border-color: var(--prio-medium-border); }
.prio-grid-btn[data-prio="high"].active   { background: var(--prio-high-bg);   color: var(--prio-high);   border-color: var(--prio-high-border); }

/* ── Group inline chip selector (params form) ── Item 8 */
/* P8: group dropdown — reuses .dl-month-picker / .dl-month-trigger / .dl-month-list /
   .dl-month-option. Only the group-specific bits live here: the colour dot, the row
   layout that holds a per-group delete button, and the "+ Создать" accent row. */
.grp-trigger-label { display: inline-flex; align-items: center; gap: 5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grp-dd-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; box-shadow: 0 0 0 1px rgba(0,0,0,0.4); }
/* gothic glyphs that stand in for the colour dot: "∅" (без группы) / cross (создать) */
.grp-trigger-label > svg, .grp-dd-opt > svg { width: 13px; height: 13px; flex-shrink: 0; opacity: 0.8; }

/* P-fix #1: the group trigger (label + sword chevron) reads violet by default — like a
   hover — and inverts to white on actual hover. Scoped to .grp-picker so the deadline/
   month/weekday triggers keep their normal white-default look. */
.grp-picker .dl-month-trigger { color: var(--accent-hover); }
.grp-picker .dl-month-trigger .dl-month-chevron { opacity: 0.85; }
.grp-picker .dl-month-trigger:hover { color: var(--text-primary); }
.grp-picker .dl-month-trigger:hover .dl-month-chevron { opacity: 1; }

/* Group option row: dot + name + delete button */
.grp-dd-opt { display: flex; align-items: center; gap: 9px; padding-right: 9px; }
.grp-dd-none { gap: 5px; }
.grp-dd-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grp-dd-del {
    flex-shrink: 0;
    width: 26px; height: 26px;
    display: flex; align-items: center; justify-content: center;
    padding: 0; margin: 0;                      /* symmetric box → equal padding around the icon */
    border: 1px solid transparent;
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--transition), background var(--transition), color var(--transition), border-color var(--transition), box-shadow var(--transition);
}
.grp-dd-del svg { width: 13px; height: 13px; pointer-events: none; display: block; }
.grp-dd-opt:hover .grp-dd-del { opacity: 0.75; }
.grp-dd-del:hover { opacity: 1; background: var(--prio-high-bg); color: var(--prio-high); border-color: var(--prio-high-border); }
/* Touch / coarse pointers can't hover — keep the delete affordance visible there */
@media (hover: none) { .grp-dd-del { opacity: 0.7; } }
/* Two-step armed state (mirrors .btn-group-action.confirm-armed) */
.grp-dd-del.confirm-armed {
    opacity: 1;
    background: var(--prio-high-bg);
    color: var(--prio-high);
    border-color: var(--prio-high-border);
    animation: armedPulse 0.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .grp-dd-del.confirm-armed { animation: none; } }

/* "+ Создать группу" — accent row that closes the list / opens the create modal */
.grp-dd-new { color: var(--accent); font-weight: 600; }
.grp-dd-new:hover { background: var(--accent-dim); color: var(--accent-hover); }

/* Archive subtasks display */
.archive-subs {
    margin-top: 7px;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 5px 10px;
}
.archive-sub {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    color: var(--text-secondary);
    opacity: 0.78;
    max-width: 100%;
}
.archive-sub.checked { opacity: 0.42; }
.archive-sub.checked .archive-sub-text { text-decoration: line-through; color: var(--text-muted); }
.archive-sub-check {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
}
.archive-sub-check svg { display: block; }
.archive-sub-text { min-width: 0; word-break: break-word; }

/* Repeat selector */
.repeat-selector { display: flex; gap: 5px; flex-wrap: wrap; justify-content: center; }
.repeat-btn {
    padding: 6px 12px;
    border-radius: 99px;
    border: 1px solid var(--border);
    font-family: var(--font-label);
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition);
    background: var(--bg-input);
    color: var(--text-secondary);
    letter-spacing: 1.5px;
}
.repeat-btn:hover:not(:disabled) { border-color: var(--border-mid); color: var(--text-primary); }
.repeat-btn.active { background: var(--accent-soft); color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.4); font-weight: 600; }
.repeat-btn:disabled {
    opacity: 0.28;
    cursor: not-allowed;
    pointer-events: none;
}

/* Deadline trigger */
.deadline-trigger {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-family: var(--font-main);
    font-size: 15px;
    cursor: pointer;
    transition: all var(--transition);
    width: 100%;
    text-align: left;
}
.deadline-trigger svg { width: 13px; height: 13px; flex-shrink: 0; }
.deadline-trigger span:not(.deadline-clear-btn) { flex: 1; }
.deadline-trigger:hover { border-color: rgba(140, 60, 255, 0.5); color: var(--accent-hover); }

.deadline-clear-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    background: transparent;
    border-radius: var(--radius-xs);
    color: var(--text-muted);
    cursor: pointer;
    flex-shrink: 0;
    transition: all var(--transition);
    border: none;
    padding: 0;
}
.deadline-clear-btn svg { width: 14px; height: 14px; display: block; }
.deadline-clear-btn:hover { background: var(--prio-high-bg); color: var(--prio-high); }
/* Remove old modal btn-dl-clear rule if any */
.btn-modal-danger.btn-dl-clear { all: unset; }

/* Note input */
.note-input {
    width: 100%;
    padding: 9px 12px;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    outline: none;
    transition: border-color var(--transition);
    font-variant-numeric: lining-nums tabular-nums;
}
.note-input::placeholder { color: var(--text-muted); font-style: italic; }
.note-input:focus { border-color: rgba(140, 60, 255, 0.5); }

/* ===== TOAST ===== */
.toast {
    position: fixed;
    bottom: max(78px, calc(24px + env(safe-area-inset-bottom, 0px)));
    left: 50%;
    transform: translateX(-50%) translateY(12px) scale(0.88);
    background: rgba(15, 5, 45, 0.97);
    color: var(--text-primary);
    border: 1px solid var(--border-mid);
    padding: 9px 22px;
    border-radius: 99px;
    font-size: 11.5px;
    font-weight: 500;
    font-family: var(--font-label);
    letter-spacing: 1px;
    opacity: 0;
    pointer-events: none;
    /* No transition — controlled entirely by animations */
    z-index: 400;  /* above modal-overlay(200) and dropdown lists(310) */
    white-space: nowrap;
    box-shadow: var(--shadow-md), 0 0 20px rgba(100, 30, 200, 0.2);
    backdrop-filter: blur(10px);
}
.toast.show {
    animation: toastAppear 0.30s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.toast.hide {
    animation: toastVanish 0.25s ease-in forwards;
}
/* Idea 7: toast with an inline "Отменить" action.
   The base .toast is pointer-events:none (pass-through message); re-enable it
   here so the undo button is actually clickable. */
.toast.has-undo { display: flex; align-items: center; gap: 12px; pointer-events: auto; }
.toast-undo-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 11px 3px 8px;
    border-radius: 99px;
    border: 1px solid var(--border-mid);
    background: var(--accent-soft);
    color: var(--accent-hover);
    font-family: var(--font-label);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    cursor: pointer;
    flex-shrink: 0;
    transition: all var(--transition);
}
.toast-undo-btn svg { width: 12px; height: 12px; flex-shrink: 0; }
.toast-undo-btn:hover { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 0 10px rgba(140, 60, 255, 0.3); }

/* Idea 1: snooze quick-menu (floating, appended to <body>) */
.snooze-menu {
    position: fixed;
    z-index: 320;
    min-width: 150px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 5px;
    background: #06021a;
    border: 1px solid rgba(140, 60, 255, 0.32);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md), 0 0 20px rgba(80, 20, 180, 0.18);
    animation: snoozeMenuIn 0.22s cubic-bezier(0.22, 1, 0.36, 1) both;
    transform-origin: top center;
}
@keyframes snoozeMenuIn {
    from { opacity: 0; transform: translateY(-7px) scale(0.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
/* Smooth exit (added by closeFloatMenu before removal) — symmetric to the open. */
.snooze-menu.float-menu-closing {
    animation: snoozeMenuOut 0.17s cubic-bezier(0.4, 0, 1, 1) both !important;
    pointer-events: none;
}
@keyframes snoozeMenuOut {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to   { opacity: 0; transform: translateY(-7px) scale(0.96); }
}
@media (prefers-reduced-motion: reduce) {
    .snooze-menu.float-menu-closing { animation: none !important; }
}
.snooze-menu button {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 12px;
    letter-spacing: 0.5px;
    cursor: pointer;
    border-radius: var(--radius-xs);
    text-align: left;
    transition: background var(--dur-micro), color var(--dur-micro);
}
.snooze-menu button svg { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.8; }
.snooze-menu button:hover { background: rgba(100, 25, 200, 0.20); color: var(--text-primary); }
@media (prefers-reduced-motion: reduce) { .snooze-menu { animation: none; } }
/* Idea 3: demote parent-picker uses the same floating menu, scrollable task list */
.snooze-menu.demote-menu { max-width: 250px; max-height: 320px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent; }
.float-menu-head {
    font-family: var(--font-label); font-size: 9.5px; letter-spacing: 1px;
    text-transform: uppercase; color: var(--accent-hover); font-weight: 600;
    padding: 3px 10px 6px;
}
.snooze-menu .float-menu-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 210px; }
/* Task-row overflow «…»: rare actions (template / duplicate / demote) */
.snooze-menu.task-more-menu { min-width: 190px; }
.snooze-menu.task-more-menu button span { white-space: nowrap; }
/* «…» glyph is a thin column — widened lozenges + a small bump balance it with
   neighbours without making its footprint exceed theirs. */
.btn-task-action.btn-task-more svg { width: 15px; height: 15px; }

/* The new sub-check mode toolbar rosette reads light/airy → enlarge it (~1.4×) so
   it carries the same visual weight as the other "вид" glyphs. */
#btn-sub-anymode svg { width: 20px; height: 20px; }

/* Demote parent-picker group headers (rendered only for non-empty buckets). */
.snooze-menu.demote-menu .demote-group-head {
    font-family: var(--font-label); font-size: 9px; letter-spacing: 1px;
    text-transform: uppercase; color: var(--accent-hover); font-weight: 600;
    padding: 8px 10px 3px;
    border-top: 1px solid rgba(140, 60, 255, 0.22);
}
.snooze-menu.demote-menu .demote-group-head:first-of-type { border-top: none; padding-top: 3px; }

/* Compact sub-check mode selector (toolbar 2-option + per-task 3-option). The
   selected radio glows with the accent so the current mode reads at a glance. A
   dedicated, more pronounced pop-in makes the open unmistakable even when it
   swaps in over the "…" menu at the same anchor. */
.snooze-menu.submode-menu,
.snooze-menu.demote-subs-menu {
    animation: subMenuPop 0.24s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes subMenuPop {
    from { opacity: 0; transform: translateY(-10px) scale(0.92); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .snooze-menu.submode-menu, .snooze-menu.demote-subs-menu { animation: none; }
}
.snooze-menu.submode-menu { min-width: 196px; }
.snooze-menu.submode-menu button span { white-space: nowrap; }
.snooze-menu.submode-menu .submode-opt.on {
    background: var(--accent-soft, rgba(110, 30, 210, 0.20));
    color: var(--text-primary);
}
.snooze-menu.submode-menu .submode-opt.on svg { opacity: 1; }
.snooze-menu.demote-subs-menu { min-width: 168px; }
.snooze-menu.demote-subs-menu button span { white-space: nowrap; }

/* ── Idea 4: quick-add typeahead dropdown (anchored under the new-task input) ── */
.qa-menu {
    position: fixed;
    z-index: 330;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 5px;
    background: #06021a;
    border: 1px solid rgba(140, 60, 255, 0.32);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md), 0 0 20px rgba(80, 20, 180, 0.18);
    max-height: 280px;
    overflow-y: auto;
    animation: snoozeMenuIn 0.14s var(--ease-emerge) both;
    scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent;
}
.qa-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 10px;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-main);
    font-size: 14px;
    cursor: pointer;
    border-radius: var(--radius-xs);
    text-align: left;
    width: 100%;
    transition: background var(--dur-micro), color var(--dur-micro);
}
.qa-item.active, .qa-item:hover { background: rgba(100, 25, 200, 0.22); color: var(--text-primary); }
.qa-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qa-hint {
    font-family: var(--font-label); font-size: 9px; letter-spacing: 0.5px;
    text-transform: uppercase; color: var(--text-muted); opacity: 0.75; flex-shrink: 0;
}
.qa-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--border-mid); }
.qa-dot-blank { background: transparent; box-shadow: inset 0 0 0 1px var(--border-mid); }
.qa-dot.prio-high   { background: var(--prio-high); }
.qa-dot.prio-medium { background: var(--prio-medium); }
.qa-dot.prio-low    { background: var(--prio-low); }
.qa-item.qa-disabled { cursor: default; opacity: 0.6; }
.qa-item.qa-disabled:hover { background: transparent; color: var(--text-secondary); }
@media (prefers-reduced-motion: reduce) { .qa-menu { animation: none; } }

/* Idea 4: quick-add syntax hint (revealed while the new-task input is focused) */
.qa-syntax-hint {
    display: flex; gap: 14px;
    max-height: 0; opacity: 0; overflow: hidden; margin-top: 0; padding-left: 4px;
    transition: max-height 0.22s var(--ease-gothic), opacity 0.2s ease, margin-top 0.22s var(--ease-gothic);
    font-family: var(--font-label); font-size: 10px; letter-spacing: 0.5px; color: var(--text-muted);
}
.qa-syntax-hint.show { max-height: 24px; opacity: 0.85; margin-top: 7px; }
.qa-syntax-hint span { display: inline-flex; align-items: center; gap: 4px; }
.qa-syntax-hint b { font-family: var(--font-mono); color: var(--accent-hover); font-weight: 600; }

/* Idea 1: snooze custom relative input */
.snooze-menu.snooze-with-custom { min-width: 172px; }
.snooze-custom {
    display: flex; align-items: center; gap: 4px;
    margin-top: 4px; padding: 6px 6px 2px;
    border-top: 1px solid var(--border);
}
.snooze-custom-input {
    width: 38px; flex-shrink: 0;
    background: var(--bg-input); border: 1px solid var(--border-input);
    border-radius: var(--radius-xs); color: var(--text-primary);
    font-family: var(--font-mono); font-size: 12px; text-align: center;
    padding: 4px 2px; outline: none; -moz-appearance: textfield;
}
.snooze-custom-input::-webkit-inner-spin-button,
.snooze-custom-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.snooze-custom-input:focus { border-color: rgba(150,70,255,0.5); }
.snooze-units { display: flex; gap: 2px; flex: 1; }
.snooze-unit {
    flex: 1; padding: 4px 2px; border: 1px solid var(--border);
    background: transparent; color: var(--text-muted);
    border-radius: var(--radius-xs); cursor: pointer;
    font-family: var(--font-label); font-size: 9.5px; transition: all var(--transition);
}
.snooze-unit:hover { color: var(--text-secondary); border-color: var(--border-mid); }
.snooze-unit.active { background: var(--accent-soft); color: var(--accent-hover); border-color: rgba(140,60,255,0.4); }
.snooze-custom-go {
    flex-shrink: 0; padding: 4px 9px; border: 1px solid rgba(140,60,255,0.4);
    background: var(--accent-soft); color: var(--accent-hover);
    border-radius: var(--radius-xs); cursor: pointer;
    font-family: var(--font-label); font-size: 9.5px; letter-spacing: 0.5px; transition: all var(--transition);
}
.snooze-custom-go:hover { background: var(--accent); color: #fff; }

/* ===== TOOLBAR ===== */
.toolbar {
    /* Stacked layout: search on its own full-width row, tool buttons on the row below.
       A single horizontal row could not fit the search field + all tool buttons, so the
       search shrank to nothing and the buttons spilled past the right border. */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 10px 14px;
    /* The same dark, violet-tinted surface every other control in the app uses —
       not the light glass slab (read as detached) the previous pass introduced. */
    background: var(--bg-input);
    border-radius: var(--radius-md);
    margin-bottom: 15px;
    border: 1px solid var(--border-mid);
    box-shadow: inset 0 1px 0 rgba(200, 140, 255, 0.05);
    backdrop-filter: blur(8px);
}

.search-wrap {
    flex: 0 0 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    padding: 7px 11px;
    transition: border-color var(--transition);
}
.search-wrap:focus-within {
    border-color: rgba(160, 80, 255, 0.75);
    /* Clean outer border only — no box-shadow inside the search field (P6) */
}
.search-wrap svg { width: 13px; height: 13px; color: var(--text-muted); flex-shrink: 0; }

#search-box {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    font-family: var(--font-main);
    font-size: 15px;
    color: var(--text-primary);
}
#search-box::placeholder { color: var(--text-muted); font-style: italic; }

/* Tool buttons live in labelled clusters (вид / фильтр / выбор / данные) separated
   by hairline gothic dividers, distributed edge-to-edge so the row reads as an
   intentional, structured bar rather than a scattered handful of icons. */
.toolbar-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-start;
    gap: 8px 0;
}
.toolbar-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 0 18px;
    position: relative;
}
.toolbar-group:first-child { padding-left: 6px; }
.toolbar-group:last-child  { padding-right: 6px; }
/* Hairline divider between adjacent clusters — fades at top/bottom like the card's seams */
.toolbar-group + .toolbar-group::before {
    content: '';
    position: absolute;
    left: 0;
    top: 4px;
    bottom: 16px;
    width: 1px;
    background: linear-gradient(180deg, transparent, rgba(160, 80, 255, 0.32) 30%, rgba(160, 80, 255, 0.32) 70%, transparent);
}
.toolbar-group-btns { display: flex; gap: 5px; }
.toolbar-group-label {
    font-family: var(--font-label);
    font-size: 9px;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: var(--text-secondary);
    opacity: 0.85;
    user-select: none;
    pointer-events: none;
}
.btn-tool {
    width: 33px;
    height: 33px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background: var(--bg-input);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition);
    padding: 0;
}
.btn-tool svg { width: 14px; height: 14px; }
.btn-tool:hover { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.5); background: var(--accent-dim); }
.btn-tool.active { background: var(--accent-soft); color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.45); }
.btn-tool.btn-danger:hover { background: var(--prio-high-bg); color: var(--prio-high); border-color: var(--prio-high-border); }

/* ===== GROUPS BAR ===== */
.groups-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 15px;
}

.btn-add-group {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 5px 12px;
    background: var(--bg-input);
    border: 1px dashed var(--border-mid);
    border-radius: 99px;
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 11px;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 2px;
    text-transform: uppercase;
}
.btn-add-group svg { width: 10px; height: 10px; }
.btn-add-group:hover { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.55); background: var(--accent-dim); }

/* group-pill styles moved to SUBTASKS section above */

/* ===== GROUP SECTION ===== */
.group-section {
    margin-bottom: 12px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: rgba(8, 2, 25, 0.5);
    backdrop-filter: blur(6px);
    transition: border-color var(--transition);
}
.group-section:hover { border-color: var(--border-mid); }

.group-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    cursor: pointer;
    background: var(--bg-group-header);
    transition: background var(--transition), transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
    user-select: none;
    border-bottom: 1px solid var(--border);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.group-header:hover { background: var(--bg-item-hover); }
/* Stone-door micro-settle: header nudges down 3px when group closes,
   as if a stone lid drops into its frame.                            */
.group-section.collapsed .group-header {
    border-bottom-color: transparent;
    border-radius: var(--radius-md);
    transform: translateY(2px);
}
/* When re-opening, header lifts back to flush */
.group-section:not(.collapsed) .group-header {
    transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
    .group-section.collapsed .group-header     { transform: none; }
    .group-section:not(.collapsed) .group-header { transform: none; }
}

.group-color-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 5px currentColor;
}

.group-title {
    font-family: var(--font-title);
    font-size: 11px;
    font-weight: 700;
    color: var(--text-primary);
    /* margin-right:auto pushes actions to the right without stretching the text
       across the full width — prevents oversized gap between title and icons */
    margin-right: auto;
    letter-spacing: 2px;
    text-transform: uppercase;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.group-count {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--text-secondary);
    background: var(--bg-tag);
    padding: 1px 7px;
    border-radius: 99px;
    border: 1px solid var(--border);
}

.group-actions { display: flex; gap: 2px; }
.btn-group-action {
    width: 26px;
    height: 26px;
    border-radius: var(--radius-xs);
    border: none;
    background: transparent;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition);
    padding: 0;
}
.btn-group-action svg { width: 12px; height: 12px; }
.btn-group-action:hover { background: var(--accent-soft); color: var(--accent-hover); border-radius: var(--radius-xs); }
.btn-group-action.danger:hover { background: var(--prio-high-bg); color: var(--prio-high); }
.btn-group-action.active-sched { color: var(--accent); background: var(--accent-soft); }
.btn-group-action.active-sched:hover { color: var(--accent-hover); }

.group-chevron {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--text-muted);
    transition: transform var(--transition-slow);
}
.group-chevron svg { width: 14px; height: 14px; pointer-events: none; display: block; }
.group-section.collapsed .group-chevron { transform: rotate(-90deg); }
/* UX-5: animated collapse — max-height driven by JS (toggleGroupCollapse sets inline
   style via scrollHeight measurement). overflow:hidden is set on .group-body.
   I-8: removed the 9999px hack — JS now sets the exact content height so the
   transition speed is consistent regardless of how many tasks are in the group. */
.group-body {
    padding: 6px;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    pointer-events: none;
    transition: max-height var(--dur-collapse) var(--ease-gothic), opacity var(--dur-collapse) var(--ease-gothic);
}
.group-body.expanded {
    opacity: 1;
    pointer-events: auto;
    /* max-height is set inline by JS to the measured scrollHeight */
}
/* After animation completes JS sets max-height to 'none' via .unlocked class */
.group-body.expanded.unlocked {
    max-height: none;
    overflow: visible;
}

/* ===== DRAG HANDLE ===== */
/* ── Drag handle removed — whole item is draggable ── */

/* ===== TASK ITEM ===== */
/* ─── BATCH-1 ANIMATIONS ──────────────────────────────────────
   Weighted rise from below — "record summoned from darkness"
   Different from the previous top-slide which felt lightweight.
   Uses --ease-gothic (stone weight) from the motion token system. */
@keyframes taskIn {
    from {
        opacity: 0;
        transform: translateY(14px) scale(0.975);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* Archive exit — slides right toward the sarcophagus nav tab.
   Semantically: "record laid to rest in the vault".           */
/* S1-1: max-height uses --row-h (the row's real height, set by JS before the exit
   class is added) instead of a hard-coded 80px — tall rows (open subtasks, note,
   2-line text, meta tags) no longer snap to 80px on frame 0 before sliding out.
   Falls back to 80px if JS didn't set the var. */
@keyframes taskArchive {
    0%   { opacity: 1;  transform: translateX(0)     scale(1);    max-height: var(--row-h, 80px); margin-bottom: 5px; padding-top: 11px; padding-bottom: 11px; }
    60%  { opacity: 0.3; transform: translateX(22px) scale(0.97); max-height: var(--row-h, 80px); }
    100% { opacity: 0;  transform: translateX(28px)  scale(0.95); max-height: 0;    margin-bottom: 0;   padding-top: 0;    padding-bottom: 0; }
}

/* Restore exit — mirror of taskArchive: slides LEFT, "record recalled from the vault". */
@keyframes taskRestore {
    0%   { opacity: 1;   transform: translateX(0)      scale(1);    max-height: var(--row-h, 80px); margin-bottom: 5px; padding-top: 11px; padding-bottom: 11px; }
    60%  { opacity: 0.3; transform: translateX(-22px)  scale(0.97); max-height: var(--row-h, 80px); }
    100% { opacity: 0;   transform: translateX(-28px)  scale(0.95); max-height: 0;    margin-bottom: 0;   padding-top: 0;    padding-bottom: 0; }
}

.archive-item.restoring {
    animation: taskRestore 0.32s ease forwards;
    pointer-events: none;
}

/* Delete exit — collapses vertically, "consumed by darkness".
   Semantically different: annihilation, not preservation.     */
@keyframes taskDelete {
    0%   { opacity: 1;  transform: scaleY(1)    translateX(0);  max-height: var(--row-h, 80px); margin-bottom: 5px; border-color: var(--border); }
    25%  { border-color: rgba(220, 30, 70, 0.55); }
    100% { opacity: 0;  transform: scaleY(0.05) translateX(-4px); max-height: 0;    margin-bottom: 0;   padding: 0; }
}

/* Coffin seal ritual — press → burst → settle.
   Uses --ease-spring (ritual-snap) from motion token system.    */
@keyframes coffinSeal {
    0%   { transform: scale(1); }
    20%  { transform: scale(0.82); }          /* pressed in */
    55%  { transform: scale(1.22); }          /* burst / overshoot */
    80%  { transform: scale(0.94); }          /* settle */
    100% { transform: scale(1); }
}

/* Coffin unseal — unchecking: rise from shadow */
@keyframes coffinUnseal {
    0%   { transform: scale(1);    opacity: 0.6; }
    50%  { transform: scale(1.15); opacity: 1;   }
    100% { transform: scale(1);    opacity: 1;   }
}

/* Border flash that fires on the task-item when checked/unchecked */
@keyframes sealFlash {
    0%   { box-shadow: inset 0 0 0 1.5px rgba(160, 80, 255, 0); }
    35%  { box-shadow: inset 0 0 0 1.5px rgba(160, 80, 255, 0.5); }
    100% { box-shadow: inset 0 0 0 1.5px rgba(160, 80, 255, 0); }
}

/* Add button seal-press — physical stamp on parchment */
@keyframes btnSeal {
    0%   { transform: scale(1); }
    30%  { transform: scale(0.84); }
    70%  { transform: scale(1.10); }
    100% { transform: scale(1); }
}

/* Progress bar milestone glow burst */
@keyframes milestoneGlow {
    0%   { box-shadow: 0 0 8px rgba(160, 80, 255, 0.5); }
    40%  { box-shadow: 0 0 22px rgba(180, 90, 255, 0.85), 0 0 40px rgba(140, 60, 255, 0.35); }
    100% { box-shadow: 0 0 8px rgba(160, 80, 255, 0.5); }
}

/* Toast spectral apparition — better spring + scale */
@keyframes toastAppear {
    from { opacity: 0; transform: translateX(-50%) translateY(12px) scale(0.88); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0)   scale(1);    }
}
@keyframes toastVanish {
    from { opacity: 1; transform: translateX(-50%) translateY(0)  scale(1);    }
    to   { opacity: 0; transform: translateX(-50%) translateY(9px) scale(0.93); }
}

/* Modal improved — veil lifts / stone falls.
   D-2: the single source of truth for @keyframes modalIn is in the MODAL section
   below; the duplicate that used to sit here was dead (the later definition won). */
@keyframes modalOut {
    from { opacity: 1; transform: scale(1)    translateY(0);    }
    to   { opacity: 0; transform: scale(0.94) translateY(12px); }
}
@keyframes overlayIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes overlayOut {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* All-done cathedral flash on the app box */
@keyframes cathedralFlash {
    0%   { box-shadow: var(--shadow-lg), 0 0 0 1px rgba(130,50,240,0.18), 0 0 45px rgba(100,25,220,0.08); }
    30%  { box-shadow: var(--shadow-lg), 0 0 0 2px rgba(200,120,255,0.65), 0 0 100px rgba(160,60,255,0.35), 0 0 200px rgba(120,40,220,0.20); }
    100% { box-shadow: var(--shadow-lg), 0 0 0 1px rgba(130,50,240,0.18), 0 0 45px rgba(100,25,220,0.08); }
}
/* ─── END BATCH-1 KEYFRAMES ────────────────────────────────── */

/* ─── BATCH-2 KEYFRAMES ──────────────────────────────────────
   counter-pop  — spring bounce on done/total digits
   strikeOut    — scaleX sweep of the strikethrough line
   ────────────────────────────────────────────────────────── */

/* Counter spring-bounce (applied to #done-count / #quantity-count) */
@keyframes counterPop {
    0%   { transform: scale(1);    }
    35%  { transform: scale(1.38); }
    65%  { transform: scale(0.90); }
    85%  { transform: scale(1.08); }
    100% { transform: scale(1);    }
}
.counter-pop {
    animation: counterPop 0.30s cubic-bezier(0.34, 1.56, 0.64, 1);
    display: inline-block; /* transform needs block context */
}

/* Strikethrough sweep — grows left→right over the checked task text.
   .task-text gains position:relative via .task-item.checked .task-text.
   The pseudo-element is the animated line.                             */
@keyframes strikeOut {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

/* ─── BATCH-3 KEYFRAMES ──────────────────────────────────────
   badgePop      — archive badge spring bounce on new item
   emptyRuneIn   — rune materialises with spin on empty state
   emptyTextIn   — text fades up after rune
   ────────────────────────────────────────────────────────── */
@keyframes badgePop {
    0%   { transform: scale(1);    }
    40%  { transform: scale(1.50); }
    65%  { transform: scale(0.88); }
    85%  { transform: scale(1.12); }
    100% { transform: scale(1);    }
}
.archive-badge.popping {
    animation: badgePop 0.34s cubic-bezier(0.34, 1.56, 0.64, 1);
    display: inline-flex !important; /* stay visible during anim */
}

@keyframes emptyRuneIn {
    0%   { transform: scale(0.3)  rotate(-45deg); opacity: 0;   }
    60%  { transform: scale(1.18) rotate(6deg);   opacity: 0.9; }
    80%  { transform: scale(0.94) rotate(-2deg);  }
    100% { transform: scale(1)    rotate(0deg);   opacity: 0.20; }
}
@keyframes emptyTextIn {
    from { opacity: 0; transform: translateY(7px); }
    to   { opacity: 0.65; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .archive-badge.popping { animation: none; }
}
/* ─── BATCH-4 KEYFRAMES  (low-priority atmospheric) ─────────────

   runeShimmer   — single light-sweep across brand name on load
   taglineAppear — each letter of "task journal" fades in staggered
   cycleSpin     — full 360° rotation of coffin on cycle-complete
   portalPulse   — pulsing border-glow on a group-body while dragging over it
   ──────────────────────────────────────────────────────────────── */

/* One-shot shimmer sweep across the DUSK logotype */
@keyframes runeShimmer {
    0%   { background-position: -200% center; }
    100% { background-position:  300% center; }
}
.brand-name.shimmer-once {
    background: linear-gradient(
        90deg,
        var(--text-primary) 20%,
        rgba(220, 170, 255, 0.95) 40%,
        rgba(255, 220, 255, 1.0)  50%,
        rgba(220, 170, 255, 0.95) 60%,
        var(--text-primary) 80%
    );
    background-size: 300% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: runeShimmer 1.1s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@media (prefers-reduced-motion: reduce) {
    .brand-name.shimmer-once { animation: none; background: none; -webkit-text-fill-color: unset; }
}

/* Tagline letter-by-letter: each span fades up individually */
@keyframes letterIn {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0);   }
}
.tagline-letter {
    display: inline-block;
    opacity: 0;
    animation: letterIn 0.22s ease forwards;
}
@media (prefers-reduced-motion: reduce) {
    .tagline-letter { animation: none; opacity: 1; }
}

/* Coffin cycle-complete: full 360° spin with slight scale bounce */
@keyframes cycleSpin {
    0%   { transform: scale(1)    rotate(0deg);   }
    25%  { transform: scale(0.88) rotate(90deg);  }
    60%  { transform: scale(1.14) rotate(280deg); }
    80%  { transform: scale(0.96) rotate(345deg); }
    100% { transform: scale(1)    rotate(360deg); }
}
.task-check.cycle-spinning,
.sub-check.cycle-spinning {
    animation: cycleSpin var(--dur-ritual) var(--ease-spring) forwards;
}
@media (prefers-reduced-motion: reduce) {
    .task-check.cycle-spinning,
    .sub-check.cycle-spinning { animation: none; }
}

/* Drop-zone portal glow: group-body glows while a task is dragged over it */
@keyframes portalPulse {
    0%, 100% { box-shadow: inset 0 0 0 1px rgba(140, 60, 255, 0.25), 0 0 12px rgba(120, 40, 240, 0.12); }
    50%       { box-shadow: inset 0 0 0 1px rgba(180, 90, 255, 0.55), 0 0 28px rgba(140, 55, 255, 0.28); }
}
.group-body.drag-over {
    animation: portalPulse 0.9s ease-in-out infinite;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
}
@media (prefers-reduced-motion: reduce) {
    .group-body.drag-over { animation: none; box-shadow: inset 0 0 0 1px rgba(140,60,255,0.4); }
}

/* ─── END BATCH-4 KEYFRAMES ───────────────────────────────────── */

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

.task-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 11px 12px;
    background: var(--bg-item);
    border-radius: var(--radius-md);
    margin-bottom: 5px;
    border: 1px solid var(--border);
    border-left: 3px solid transparent;
    /* The ONLY glow a task carries is a small, subtle bleed just left of its stripe,
       coloured to match it. Set per stripe-type via --stripe-glow; transparent by
       default (plain tasks have no glow). Kept consistent across hover too. */
    --stripe-glow: 0 0 transparent;
    box-shadow: var(--stripe-glow);
    transition: background var(--transition), border-color var(--transition),
                box-shadow var(--transition), opacity 0.25s ease;
    position: relative;
    backdrop-filter: blur(4px);
    overflow: hidden;
    cursor: grab;
    /* Critical for reliable drag: prevent text selection */
    -webkit-user-select: none;
    user-select: none;
}
/* taskIn animation only for freshly added items (.entering added by JS) */
.task-item.entering {
    animation: taskIn var(--dur-standard) var(--ease-gothic);
}
/* reentering: smooth fade-in when task is unchecked/restored */
.task-item.reentering {
    animation: taskUncheckIn 0.28s var(--ease-gothic) both;
}
@keyframes taskUncheckIn {
    from { opacity: 0.55; transform: scale(0.99); }
    to   { opacity: 1;    transform: scale(1); }
}
/* Problem 4: a task fades + drifts out of its old row before re-rendering in its
   new active/completed position, so the move reads smoothly instead of the row
   just vanishing. Mirrors the subtask checking-out behaviour. Works in both the
   normal list and the split active/done zones.
   NOTE: no `from` keyframe — the animation starts from the row's CURRENT opacity
   (1 when active, 0.65 when checked) so unchecking a completed row fades cleanly
   without a brightness jump. `!important` is required because .task-item.checked
   also sets `animation` (taskCheckIn) and would otherwise win on source order. */
@keyframes taskLeave {
    to { opacity: 0; transform: scale(0.97) translateX(8px); }
}
.task-item.task-leaving {
    animation: taskLeave 0.20s var(--ease-sink) forwards !important;
    pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
    .task-item.entering { animation: none; }
    .task-item.task-leaving { animation: none; }
}
/* "Settle into the new slot" after a check/uncheck move (added by JS to the
   rebuilt row / subtask). No `to`/`both` keyframe → the item lands on its natural
   opacity (1 active, 0.65 checked) with no flash; `!important` beats taskCheckIn so
   a checked row fades in cleanly instead of popping in then dimming. */
@keyframes itemSettleIn {
    0%   { opacity: 0; transform: translateY(-12px) scale(0.94); }
    55%  { opacity: 1; }
    100% { transform: translateY(0) scale(1); }
}
.task-item.settling-in    { animation: itemSettleIn 0.38s var(--ease-gothic); }
.subtask-item.settling-in { animation: itemSettleIn 0.32s var(--ease-gothic); }
@media (prefers-reduced-motion: reduce) {
    .task-item.settling-in, .subtask-item.settling-in { animation: none; }
}
/* Recurring cycle-complete card pulse — glow + slight rotate/scale that resonates
   with the coffin's 360° spin (added by _cycleSettle). Lands on the cycle-checked
   natural opacity (0.65) — no `to` opacity, so no flash. */
@keyframes cycleCardSettle {
    0%   { opacity: 0;    transform: scale(0.90) rotate(-5deg);  box-shadow: 0 0 0 0 rgba(168, 96, 255, 0); }
    45%  { opacity: 1;    transform: scale(1.025) rotate(1.5deg); box-shadow: 0 0 22px 2px rgba(168, 96, 255, 0.42); }
    100% {                transform: scale(1) rotate(0);          box-shadow: 0 0 0 0 rgba(168, 96, 255, 0); }
}
.task-item.cycle-settling { animation: cycleCardSettle 0.5s cubic-bezier(0.34, 1.4, 0.5, 1); }
@media (prefers-reduced-motion: reduce) { .task-item.cycle-settling { animation: none; } }
/* Same ritual for a recurring SUBTASK card. Glow via filter:drop-shadow (not
   box-shadow) so the subtask's inset outline survives the pulse; smaller rotate
   to read well inside the 2-col grid. Lands on natural opacity (no `to`). */
@keyframes subCycleCardSettle {
    0%   { opacity: 0; transform: scale(0.92) rotate(-3deg); filter: drop-shadow(0 0 0 rgba(168, 96, 255, 0)); }
    45%  { opacity: 1; transform: scale(1.03) rotate(1deg);  filter: drop-shadow(0 0 9px rgba(168, 96, 255, 0.6)); }
    100% {             transform: scale(1) rotate(0);        filter: drop-shadow(0 0 0 rgba(168, 96, 255, 0)); }
}
.subtask-item.cycle-settling { animation: subCycleCardSettle 0.46s cubic-bezier(0.34, 1.4, 0.5, 1); }
@media (prefers-reduced-motion: reduce) { .subtask-item.cycle-settling { animation: none; } }

/* Auto-check feedback: a check pulse on the CURRENT (plain) card BEFORE it re-renders,
   so an auto-checked parent / its triggering subtask show a clear check even when the
   filter then hides them. Recurring items use the coffin spin instead. Subtask glow
   uses filter:drop-shadow so its inset outline survives. */
@keyframes checkPulse {
    0%   { box-shadow: 0 0 0 0 rgba(168, 96, 255, 0); }
    35%  { transform: scale(1.05); box-shadow: 0 0 26px 3px rgba(168, 96, 255, 0.6); }
    100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(168, 96, 255, 0); }
}
.task-item.check-pulse { animation: checkPulse 0.34s var(--ease-spring); }
@keyframes checkPulseSub {
    0%   { filter: drop-shadow(0 0 0 rgba(168, 96, 255, 0)); }
    35%  { transform: scale(1.06); filter: drop-shadow(0 0 11px rgba(168, 96, 255, 0.75)); }
    100% { transform: scale(1); filter: drop-shadow(0 0 0 rgba(168, 96, 255, 0)); }
}
.subtask-item.check-pulse { animation: checkPulseSub 0.34s var(--ease-spring); }
/* Auto-UNcheck feedback: a cool "release / unseal" dip (scale-DOWN + dimmer cool
   glow) — deliberately distinct from the check seal-pulse so an auto-uncleared
   parent + its triggering subtask read clearly when a sub is un-done in any/all mode. */
@keyframes uncheckPulse {
    0%   { box-shadow: 0 0 0 0 rgba(150, 130, 205, 0); }
    35%  { transform: scale(0.965); box-shadow: 0 0 20px 2px rgba(150, 130, 205, 0.4); }
    100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(150, 130, 205, 0); }
}
.task-item.uncheck-pulse { animation: uncheckPulse 0.34s var(--ease-gothic); }
@keyframes uncheckPulseSub {
    0%   { filter: drop-shadow(0 0 0 rgba(150, 130, 205, 0)); }
    35%  { transform: scale(0.95); filter: drop-shadow(0 0 8px rgba(150, 130, 205, 0.5)); }
    100% { transform: scale(1); filter: drop-shadow(0 0 0 rgba(150, 130, 205, 0)); }
}
.subtask-item.uncheck-pulse { animation: uncheckPulseSub 0.34s var(--ease-gothic); }
@media (prefers-reduced-motion: reduce) {
    .task-item.check-pulse, .subtask-item.check-pulse,
    .task-item.uncheck-pulse, .subtask-item.uncheck-pulse { animation: none; }
}
/* Allow text selection only in editable areas */
.task-item .task-text[contenteditable="true"] { user-select: text; -webkit-user-select: text; }
.task-item .task-note-text.editing           { user-select: text; -webkit-user-select: text; }
/* Restore pointer cursor on clickable children */
.task-item .btn-task-action,
.task-item .task-check,
.task-item .btn-note-toggle,
.task-item .btn-subtask-toggle,
.task-item .btn-note-delete,
.task-item .sub-check,
.task-item .sub-prio-btn,
.task-item .btn-sub-action,
.task-item .hashtag,
.task-item .meta-tag { cursor: pointer; }

.task-item:hover {
    background: var(--bg-item-hover);
    border-color: var(--border-mid);
    /* depth shadow only — no ambient purple glow; the stripe glow persists */
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.4), var(--stripe-glow);
}
/* ANIM-4: while the entrance animation is running, don't respond to hover
   so the fade-in and background-hover don't fight each other visually. */
.task-item.entering:hover {
    background: var(--bg-item);
    border-color: var(--border);
    box-shadow: none;
    transition: none;
}

/* Priority stripe — colour the border + a small glow ONLY to the left of it.
   The negative spread (== blur) collapses the shadow vertically so it never
   bleeds past the top/bottom edges; only the left x-offset escapes the box. */
.task-item[data-prio="high"]   { border-left-color: var(--prio-high);   --stripe-glow: -5px 0 5px -5px rgba(220, 30, 70, 0.60); }
.task-item[data-prio="medium"] { border-left-color: var(--prio-medium); --stripe-glow: -5px 0 5px -5px rgba(210, 120, 20, 0.55); }
.task-item[data-prio="low"]    { border-left-color: var(--prio-low);    --stripe-glow: -5px 0 5px -5px rgba(40, 200, 80, 0.48); }

/* ── Task color label — custom left stripe via CSS var ──────────────────────
   Set by JS: li.style.setProperty('--task-color', '#hex') when task.color exists. */
.task-item:has(> [style*="--task-color"]),
.task-item[style*="--task-color"] {
    border-left-color: var(--task-color, transparent);
    --stripe-glow: -5px 0 5px -5px color-mix(in srgb, var(--task-color, transparent) 65%, transparent);
}

/* Task color picker in modal */
/* Recommended presets — fixed 5-column grid → always a symmetric 5×2 block */
.task-color-picker {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 11px;
    justify-items: center;
    padding: 6px 0 12px;
}
.btn-task-color {
    transition: color var(--transition), opacity var(--transition);
}

/* ── Gothic custom-colour spectrum (RGB picker) ───────────────────────────── */
.modal.modal-color { width: 348px; max-width: calc(100vw - 24px); }
.gothic-rgb {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 12px;
    margin-top: 4px;
    border-top: 1px solid var(--border);
}
/* 2D saturation (x) / value (y) pad — base hue set by JS via --grgb-hue */
.grgb-pad {
    position: relative;
    width: 100%;
    height: 116px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    cursor: crosshair;
    touch-action: none;
    background:
        linear-gradient(to top, #000, transparent),
        linear-gradient(to right, #fff, transparent),
        hsl(var(--grgb-hue, 270), 100%, 50%);
    box-shadow: inset 0 0 18px rgba(0,0,0,0.35);
}
.grgb-thumb {
    position: absolute;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,0.9);
    box-shadow: 0 0 0 1px rgba(0,0,0,0.5), 0 0 6px rgba(0,0,0,0.5);
    transform: translate(-50%, -50%);
    pointer-events: none;
}
/* Hue band — styled native range so it stays keyboard/touch accessible */
.grgb-hue {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 14px;
    border-radius: 7px;
    border: 1px solid var(--border-mid);
    background: linear-gradient(to right,
        #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
    cursor: pointer;
}
.grgb-hue::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 12px;
    height: 20px;
    border-radius: 3px;
    background: linear-gradient(180deg, #f0e8ff, #b880e8);
    border: 1px solid rgba(20,8,40,0.8);
    box-shadow: 0 0 6px rgba(160,80,255,0.6);
    cursor: pointer;
}
.grgb-hue::-moz-range-thumb {
    width: 12px;
    height: 20px;
    border-radius: 3px;
    background: linear-gradient(180deg, #f0e8ff, #b880e8);
    border: 1px solid rgba(20,8,40,0.8);
    box-shadow: 0 0 6px rgba(160,80,255,0.6);
    cursor: pointer;
}
.grgb-foot {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 9px;
}
.grgb-preview {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    flex-shrink: 0;
    box-shadow: inset 0 0 8px rgba(0,0,0,0.4);
}
.grgb-hex {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-secondary);
    letter-spacing: 0.5px;
    min-width: 64px;
}
.grgb-apply {
    margin-left: auto;
    padding: 7px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(140, 60, 255, 0.45);
    background: var(--accent-soft);
    color: var(--accent-hover);
    font-family: var(--font-label);
    font-size: 10.5px;
    letter-spacing: 1px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all var(--transition);
    white-space: nowrap;
}
.grgb-apply:hover { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 0 12px rgba(140,60,255,0.3); }
.grgb-clear {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 7px 11px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background: transparent;
    color: var(--text-muted);
    font-family: var(--font-label);
    font-size: 10.5px;
    letter-spacing: 1px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all var(--transition);
    white-space: nowrap;
}
.grgb-clear svg { width: 13px; height: 13px; flex-shrink: 0; }
.grgb-clear:hover { color: var(--text-secondary); border-color: var(--border-bright); background: var(--bg-input); }

/* ── Pinned task visual — dagger stripe on left, faint ethereal glow ───────── */
.task-item.pinned:not(.checked):not(.cycle-checked) {
    border-left-color: rgba(180, 100, 255, 0.75);
    background: linear-gradient(
        90deg,
        rgba(120, 40, 220, 0.08) 0%,
        transparent 28%
    ), var(--bg-item);
    box-shadow: -2px 0 10px rgba(140, 50, 255, 0.20),
                inset 0 0 24px rgba(100, 20, 200, 0.04);
}
/* Pin button — glows when active (task is pinned) */
.btn-task-action.btn-pin.active {
    color: rgba(200, 130, 255, 0.95);
    opacity: 1;
}
.btn-task-action.btn-pin {
    transition: color var(--transition), opacity var(--transition);
}

/* Forged spike driven into the top-left corner of a pinned card. */
.pin-spike {
    position: absolute;
    top: 1px;
    left: 1px;
    width: 18px;
    height: 18px;
    color: var(--accent-hover);
    pointer-events: none;
    z-index: 4;
    filter: drop-shadow(0 0 4px rgba(160, 96, 255, 0.55));
    animation: pinSpikeIn 0.34s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.pin-spike svg { width: 100%; height: 100%; display: block; }
/* A completed pin loses its spike (it leaves the pinned zone anyway). */
.task-item.checked .pin-spike,
.task-item.cycle-checked .pin-spike { display: none; }
@keyframes pinSpikeIn {
    from { opacity: 0; transform: translate(-3px, -3px) rotate(-12deg); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .pin-spike { animation: none; }
}

/* Checked state — readable but visually subdued */
.task-item.checked {
    background: var(--bg-item-checked);
    opacity: 0.65;
    border-left-color: transparent !important;
    box-shadow: none !important;
    cursor: not-allowed;   /* P3: drag forbidden — show not-allowed cursor */
}
/* Dim is now STATIC (no replay-on-render `both` animation). The check/uncheck
   move-entrance is driven by .settling-in (itemSettleIn) / .cycle-settling, so the
   row animates every toggle instead of only the first, with no re-dim flash. */
.task-item.cycle-checked {
    opacity: 0.65;
}
@keyframes taskCheckIn {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0.65; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .task-item.checked,
    .task-item.cycle-checked { animation: none; }
}
.task-item.checked:hover { opacity: 0.85; cursor: not-allowed; }
/* Cycle-checked also not draggable */
.task-item.cycle-checked { cursor: not-allowed; }
.task-item.cycle-checked:hover { cursor: not-allowed; }

/* In the done-zone archive the not-allowed cursor is meaningless —
   tasks there are already archived, DnD is disabled for a different reason.
   Restore default pointer so the zone feels like a read-only list, not an error state. */
.split-done-body .task-item.checked,
.split-done-body .task-item.checked:hover,
.split-done-body .task-item.cycle-checked,
.split-done-body .task-item.cycle-checked:hover { cursor: default; }

/* Unify ALL cursors inside the archive — text cursor on task-text is also
   out of place here since tasks are read-only. One consistent default. */
.split-done-body,
.split-done-body * { cursor: default !important; }
/* …except interactive buttons — restore pointer so they still feel clickable */
.split-done-body button,
.split-done-body [role="button"],
.split-done-body .task-check,
.split-done-body .btn-task-action { cursor: pointer !important; }

/* ── Archive month sections (Extension 11) ───────────────────── */
.archive-month-section { margin-bottom: 6px; }
.archive-month-header {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 10px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border);
    color: var(--text-secondary);
    cursor: pointer;
    font-family: var(--font-label);
    font-size: 10px;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    transition: color var(--transition);
    margin-bottom: 4px;
}
.archive-month-header:hover { color: var(--text-primary); }
.archive-month-name { flex: 1; text-align: left; }
.archive-month-count {
    font-size: 9px;
    opacity: 0.5;
    background: var(--bg-item);
    border: 1px solid var(--border);
    border-radius: 99px;
    padding: 1px 7px;
    font-weight: 600;
}
.archive-month-chevron {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    transition: transform var(--transition-slow);
}
.archive-month-section.collapsed .archive-month-chevron { transform: rotate(-90deg); }
.archive-month-body {
    list-style: none;
    overflow: hidden;
    max-height: 9999px;
    opacity: 1;
    transition: max-height var(--dur-collapse) var(--ease-gothic), opacity var(--dur-collapse) var(--ease-gothic);
    padding: 0;
    margin: 0;
}
.archive-month-section.collapsed .archive-month-body {
    max-height: 0;
    opacity: 0;
    pointer-events: none;
}

/* ── Архив: унифицированный курсор ──────────────────────────── */
.archive-item,
.archive-item.checked,
.archive-item.checked:hover,
.archive-item.cycle-checked,
.archive-item.cycle-checked:hover,
.archive-item .task-text,
.archive-item .meta-tag,
.archive-item .task-note-text,
.archive-item .archive-sub-text,
.archive-item .archive-sub-check,
.archive-item .arch-check {
    cursor: default !important;
}
.archive-item .btn-task-action,
.archive-item .restore-btn {
    cursor: pointer !important;
}
/* Fix 5: in select mode the whole item + check indicator are clickable */
.archive-item.select-mode,
.archive-item.select-mode .arch-check,
.archive-item.select-mode .arc-select-indicator,
.archive-item.select-mode .task-text,
.archive-item.select-mode .meta-tag {
    cursor: pointer !important;
}
.archive-item.select-mode:hover {
    background: rgba(100, 30, 200, 0.10);
    border-color: rgba(140, 60, 240, 0.38);
}

/* Cycle-checked — "done until next reset": understated but clearly distinct. */
.task-item.cycle-checked {
    background: var(--bg-item);
    border-left: 2px dashed rgba(140, 60, 240, 0.55);
    border-color: rgba(100, 35, 190, 0.28);
}
.task-item.cycle-checked:hover {
    background: rgba(30, 6, 80, 0.18);
    border-color: rgba(130, 50, 210, 0.40);
}
/* Cycle-checked text: slight mute but still readable */
.task-item.cycle-checked .task-text {
    color: rgba(200, 170, 240, 0.78);
}

.task-item.removing          { animation: taskArchive 0.32s ease forwards; pointer-events: none; }
.task-item.removing-forever  { animation: taskDelete  0.28s cubic-bezier(0.55, 0, 1, 0.45) forwards;
                                transform-origin: top center; pointer-events: none; }

/* Coffin seal ritual classes */
.task-check.sealing   { animation: coffinSeal   var(--dur-quick) var(--ease-spring) forwards; }
.task-check.unsealing { animation: coffinUnseal var(--dur-quick) ease-out forwards; }
.task-item.seal-flash { animation: sealFlash 0.4s ease forwards; }

/* Milestone glow classes (added/removed by JS) */
.progress-bar-fill.milestone-glow { animation: milestoneGlow 0.6s ease forwards; }

/* ── Item 6: Schedule mode — side deadline panel ── */
.task-item.has-dl-side {
    padding-left: 0;
}
.dl-side-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 54px;
    max-width: 54px;
    padding: 6px 4px;
    border-right: 1px solid var(--border-mid);
    margin-right: 10px;
    flex-shrink: 0;
    align-self: stretch;
    background: rgba(18, 4, 50, 0.60);
    border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.dl-side-countdown {
    font-family: var(--font-mono);
    font-size: 9.5px;
    font-weight: 700;
    color: var(--accent-hover);
    text-align: center;
    line-height: 1.3;
    word-break: break-word;
}
.dl-side-date {
    font-family: var(--font-mono);
    font-size: 8.5px;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.3;
    word-break: break-word;
}
.dl-side-panel.dl-side-over {
    border-right-color: var(--prio-high);
    background: rgba(120,5,35,0.28);
}
.dl-side-panel.dl-side-over .dl-side-countdown,
.dl-side-panel.dl-side-over .dl-side-date { color: var(--prio-high); }
.dl-side-panel.dl-side-critical {
    border-right-color: var(--deadline-critical);
    background: rgba(120,5,35,0.22);
    animation: pulseSide 1.6s ease infinite;
}
.dl-side-panel.dl-side-critical .dl-side-countdown { color: var(--deadline-critical); }
.dl-side-panel.dl-side-urgent {
    border-right-color: var(--deadline-urgent);
    background: rgba(90,40,5,0.25);
}
.dl-side-panel.dl-side-urgent .dl-side-countdown { color: var(--deadline-urgent); }
.dl-side-panel.dl-side-warn   { border-right-color: var(--deadline-warn); }
.dl-side-panel.dl-side-warn   .dl-side-countdown { color: var(--deadline-warn); }
@keyframes pulseSide {
    0%, 100% { box-shadow: none; }
    50%       { box-shadow: inset 0 0 10px rgba(220,30,70,0.18); }
}

/* ── Schedule mode subgroup dividers ── */
.dl-subgroup-header {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    margin: 6px 0 3px;
    font-family: var(--font-label);
    font-size: 10px;
    /* P6: matches split-zone-header contrast — var(--text-secondary) = #b880e8 */
    color: var(--text-secondary);
    letter-spacing: 1.5px;
    text-transform: uppercase;
    border-bottom: 1px solid var(--border);
    pointer-events: none;
    user-select: none;
}
.dl-subgroup-header > span {
    display: flex;
    align-items: center;
    gap: 5px;
}
/* P6+P8: icon at full current-color opacity — no dimming, matches text */
.dl-subgroup-header svg { width: 10px; height: 10px; opacity: 1; }
/* P6: Без дедлайна same contrast as С дедлайном */
.dl-subgroup-nodl { color: var(--text-secondary); margin-top: 10px; }
.dl-subgroup-nodl svg { opacity: 1; }

/* P7: schedule + split combined — inner split zone sits visually inside the
   deadline bucket: left border + padding creates clear parent/child hierarchy */
.sched-split-inner {
    list-style: none;
    padding: 0 0 0 10px;
    margin: 0;
    border-left: 2px solid rgba(100, 35, 170, 0.28);
    margin-left: 4px;
}
/* Tighten the split-zone-header inside the nested zone */
.sched-split-inner .split-zone-header {
    font-size: 10.5px;
    padding: 4px 6px 4px;
    margin: 5px 0 3px;
}


/* ── Drag & drop gothic polish ────────────────────────────────
   chosen:  slight tilt — like a manuscript picked up by a hand
   ghost:   ink silhouette — the shadow of the record remains
            animation:none stops taskIn from overriding opacity
   drag:    heavier shadow — weight of the lifted stone slab
   ghost-settling: CSS transition settle after drop (no keyframe
            conflict — just lets opacity/filter return naturally)  */
.sortable-ghost {
    opacity: 0.28 !important;
    animation: none !important;          /* ← KEY FIX: stops taskIn fighting ghost opacity */
    background: rgba(60, 15, 140, 0.22) !important;
    border-color: rgba(130, 55, 240, 0.40) !important;
    filter: sepia(0.65) saturate(0.32) brightness(0.78);
    transition: none !important;
}
.sortable-chosen {
    box-shadow: 0 0 0 1px var(--accent), var(--shadow-md), 0 0 20px rgba(140, 60, 255, 0.2) !important;
    z-index: 20;
    cursor: grab !important;
    transform: rotate(-1.2deg) scale(1.01);
    transition: transform 0.12s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
}
.sortable-drag {
    cursor: grabbing !important;
    box-shadow: var(--shadow-lg), 0 0 40px rgba(120, 40, 240, 0.32), 0 8px 24px rgba(0,0,0,0.6);
    opacity: 0.96;
    transform: rotate(-1.2deg) scale(1.01);
}

/* After drop: item transitions smoothly from ghost state back to normal.
   Applied inline via JS (opacity + filter + transition), so no keyframe
   conflicts with taskIn. Class just exists for reduced-motion guard.  */
.ghost-settling {
    /* intentionally empty — real settling done via inline style transition */
}

@media (prefers-reduced-motion: reduce) {
    .sortable-chosen  { transform: none; }
    .sortable-drag    { transform: none; }
    .sortable-ghost   { filter: none; }
}

/* ===== COFFIN CHECKBOX ===== */
.task-check {
    width: 21px;
    height: 27px;
    min-width: 21px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    margin-top: 0;
    transition: all 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
    background: transparent;
    border: none;
    padding: 0;
}
.task-check svg { transition: all 0.22s ease; }
.task-check:hover svg { filter: drop-shadow(0 0 4px rgba(160, 80, 255, 0.6)); transform: scale(1.1); }

/* Checked: filled coffin — purple */
.task-item.checked .task-check svg .coffin-body {
    fill: url(#coffinGrad);
    stroke: rgba(180, 100, 255, 0.8);
}
/* Cycle-checked: uses same coffinGrad as completed — same quality, different icon */
.task-item.cycle-checked .task-check svg .coffin-body {
    fill: url(#coffinGrad);
    stroke: rgba(160, 80, 255, 0.70);
}

/* Sub-item coffin (smaller) */
.sub-check {
    width: 16px;
    height: 20px;
    min-width: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: all 0.18s ease;
    border: none;
    background: transparent;
    padding: 0;
}
.sub-check:hover svg { filter: drop-shadow(0 0 3px rgba(160,80,255,0.5)); }
.subtask-item.checked .sub-check svg .coffin-body { fill: url(#coffinGrad); stroke: rgba(180,100,255,0.8); }

/* ===== GROUP PILL WITH DELETE ===== */
.group-pill-wrap {
    display: inline-flex;
    align-items: center;
    gap: 0;
    position: relative;
}
.meta-tag.group-pill {
    border-radius: 99px;
    padding: 4px 11px;
    height: 26px;
    font-size: 10.5px;
    font-weight: 600;
    font-family: var(--font-mono);
    letter-spacing: 0.3px;
    white-space: nowrap;
    cursor: default;
    display: inline-flex;
    align-items: center;
    transition: padding-right var(--transition), border-radius var(--transition);
}
/* When hovered: right side flattens to make room for delete button. padding-right
   is tightened so the tombstone ✕ sits centred between the name and the pill's
   right border (the text-side gap was ~5px larger than the border-side gap). */
.group-pill-wrap:hover .meta-tag.group-pill {
    border-radius: 99px 0 0 99px;
    padding-right: 3px;
    border-right: none;
}
.btn-pill-delete {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 26px;
    min-width: 0;
    width: 0;
    padding: 0;
    overflow: hidden;
    border-radius: 0 99px 99px 0;
    border: 1px solid transparent;
    border-left: none;
    cursor: pointer;
    opacity: 0;
    transition: all var(--transition);
    line-height: 1;
}
.group-pill-wrap:hover .btn-pill-delete {
    width: 26px;
    min-width: 26px;
    padding: 4px 7px 4px 5px;
    opacity: 1;
}
.btn-pill-delete svg { width: 11px; height: 11px; pointer-events: none; flex-shrink: 0; }

/* ===== SUBTASKS ===== */
/* ── Smooth animation via inner wrapper ── */
.subtask-section {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height var(--dur-collapse) var(--ease-gothic), opacity var(--dur-collapse) var(--ease-gothic);
    margin-top: 0;
    /* Subtasks fill the task-content column. The task-actions now live INSIDE
       .task-content (in .task-head), so .task-content already spans the full
       task-item width — no horizontal break-out is needed (an old -209px right
       margin used to reach under the action buttons and now overflows). */
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
}
.subtask-section.open {
    max-height: none;   /* I-4: was hardcoded 1200px — removed to support any number of subtasks */
    opacity: 1;
    margin-top: 8px;
}
.sub-section-inner {
    /* inner wrapper so scrollHeight is measurable */
}

/* S1-2: honour reduced-motion for every JS-driven collapse. These are max-height
   transitions (not @keyframes), so the keyframe-focused reduced-motion rules
   elsewhere missed them. The JS finishers still run via onMaxHeightEnd()'s
   fallback timer, so state stays consistent without the height animation. */
@media (prefers-reduced-motion: reduce) {
    .extra-fields,
    .group-body,
    .subtask-section,
    .sub-note-wrapper,
    .sub-note-inner,
    .sub-deadline-wrapper,
    .sub-deadline-inner {
        transition: none !important;
    }
    /* P-E: no pulsing critical glyph under reduced motion */
    .sub-deadline-badge.sub-dl-critical { animation: none !important; }
}

/* ── Item 1: subtask progress bar ── */
.sub-progress-bar-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 5px;
    padding: 2px 4px;
    position: relative;
}
.sub-progress-bar-track {
    flex: 1;
    height: 1.5px;
    background: var(--border);
    border-radius: 99px;
    overflow: hidden;
    min-width: 0;
}
.sub-progress-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, rgba(110,45,200,0.60), rgba(175,95,255,0.72));
    border-radius: 99px;
    transition: width 0.4s ease;
}
.sub-progress-label {
    font-family: var(--font-label);
    font-size: 9.5px;
    color: var(--text-muted);
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── Item 5: 2 subtasks per row ── */
.subtask-list {
    list-style: none;
    display: grid;
    /* minmax(0,1fr) (not bare 1fr = minmax(auto,1fr)) so a wide item can never
       push the column past the container and get its right border clipped. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3px;
    margin-bottom: 5px;
    min-height: 2px;
    /* The right column's fractional width can nudge its edge a hair past the
       section's overflow:hidden, clipping the right outline. A 2px right inset
       keeps the column edge inside the clip so the outline always shows. */
    padding-right: 2px;
}
/* Problem 6: a subtask left alone on the final row (odd count) stretches to the
   full width instead of sitting awkwardly in the left half. Applies to the
   normal 2-column list (split-mode grids handle this in their own rule). */
.subtask-list:not(.sub-split-mode) > .subtask-item:last-child:nth-child(odd) {
    grid-column: 1 / -1;
}

/* ── Item 7: fix vertical text — main-row is the flex container ── */
/* Subtask item enter/exit animation */
.subtask-item {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 5px 8px;
    background: rgba(8, 2, 28, 0.65);
    border-radius: var(--radius-sm);
    /* Outline via inset box-shadow, NOT a 1px border: a hairline border on a
       fractional-width grid item (minmax(0,1fr) columns land on sub-pixel x)
       drops out at pixel-snapping — randomly on left/right of either column.
       An inset shadow paints the full outline crisply at any position. */
    border: none;
    box-shadow: inset 0 0 0 1px var(--border);   /* symmetric outline on all edges */
    transition: background var(--transition), border-color var(--transition),
                box-shadow var(--transition), opacity 0.22s ease, transform 0.22s ease;
    position: relative;
    cursor: grab;
    -webkit-user-select: none;
    user-select: none;
}
.subtask-item:hover { background: rgba(18, 5, 50, 0.80); border-color: var(--border-mid); box-shadow: inset 0 0 0 1px var(--border-mid); }
/* Priority accent: a soft rounded "ember" bar inset near the left edge with a
   faint glow that bleeds the priority colour into the body — complements the
   rounded container instead of being a hard vertical line. Drawn as ::before so
   the box-shadow outline stays symmetric on all four edges. The colour comes
   from --sprio (set per priority); absent → transparent → invisible. */
.subtask-item::before {
    content: '';
    position: absolute;
    left: 3px;
    top: 5px;
    bottom: 5px;
    width: 3px;
    border-radius: 99px;
    background: var(--sprio, transparent);
    box-shadow: 0 0 5px 0 var(--sprio, transparent);
    opacity: 0.9;
    pointer-events: none;
    transition: background var(--transition), box-shadow var(--transition), opacity var(--transition);
}
.subtask-item[data-sprio="high"]   { --sprio: var(--prio-high); }
.subtask-item[data-sprio="medium"] { --sprio: var(--prio-medium); }
.subtask-item[data-sprio="low"]    { --sprio: var(--prio-low); }
/* Restore pointer on interactive subtask children */
.subtask-item .sub-check,
.subtask-item .sub-prio-btn,
.subtask-item .btn-sub-action { cursor: pointer; }
/* ── Checked subtask: fades, strikethrough preserving line wrap ── */
.subtask-item.checked {
    opacity: 0.55;
    cursor: not-allowed;
    transition: opacity 0.25s ease;   /* static dim; entrance handled by .settling-in */
}
.subtask-item.checked::before { opacity: 0; } /* fade out priority accent when done */
@keyframes subCheckIn {
    from { opacity: 1; }
    to   { opacity: 0.55; }
}
@media (prefers-reduced-motion: reduce) {
    .subtask-item.checked { animation: none; }
}
.subtask-item.checked:hover { opacity: 0.72; cursor: not-allowed; }
/* Restore pointer on interactive children inside checked subtask */
.subtask-item.checked .sub-check,
.subtask-item.checked .btn-sub-action { cursor: pointer; }

/* Strikethrough: text-decoration works on every wrapped line.
   Animate via text-decoration-color from transparent to visible.            */
.subtask-item.checked .sub-text {
    color: rgba(160, 120, 210, 0.65);
    flex: 1;
    text-decoration: line-through;
    text-decoration-color: rgba(130, 80, 190, 0.50);
    text-decoration-thickness: 1.2px;
    animation: subStrikeIn 0.28s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes subStrikeIn {
    from { text-decoration-color: transparent; color: var(--text-primary); }
    to   { text-decoration-color: rgba(130, 80, 190, 0.50); color: rgba(160, 120, 210, 0.65); }
}

@media (prefers-reduced-motion: reduce) {
    .subtask-item.checked .sub-text { animation: none; }
}

/* The actual flex row inside each subtask item */
.sub-main-row {
    display: flex;
    align-items: center;
    gap: 5px;
    width: 100%;
}

/* ── Split-mode item animations ──────────────────────────────────────── */
@keyframes splitItemIn {
    from { opacity: 0; transform: translateY(-4px) scale(0.98); }
    to   { opacity: 1; transform: none; }  /* end at none (not identity) so no
                                              lingering compositing layer blurs the hairline outline */
}
/* Items appear with stagger when split section rebuilds */
.sub-split-inner .subtask-item {
    animation: splitItemIn 0.22s cubic-bezier(0.4, 0, 0.2, 1) both;
}
.sub-split-inner .subtask-item:nth-child(even) { animation-delay: 0.04s; }
@media (prefers-reduced-motion: reduce) {
    .sub-split-inner .subtask-item { animation: none; }
}
/* Checking-out / checking-in transitions triggered by JS */
@keyframes checkingOut {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0; transform: scale(0.94) translateX(6px); }
}
@keyframes checkingIn {
    from { opacity: 0; transform: scale(0.94) translateX(-6px); }
    to   { opacity: 1; transform: scale(1); }
}
.subtask-item.checking-out { animation: checkingOut 0.16s var(--ease-sink) forwards; pointer-events: none; }
.subtask-item.checking-in  { animation: checkingIn  0.16s var(--ease-gothic) both; }

/* Problem 5: smooth add / remove of a single subtask.
   .sub-adding is applied to the freshly inserted item only (so other items don't
   re-flash on rebuild); it wins over splitItemIn via equal specificity + source
   order. .sub-removing fades the item out before it's deleted from state. */
@keyframes subItemAdd {
    from { opacity: 0; transform: translateY(-6px) scale(0.95); }
    to   { opacity: 1; transform: none; }
}
@keyframes subItemRemove {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0; transform: scale(0.93) translateX(6px); }
}
.subtask-item.sub-adding   { animation: subItemAdd 0.26s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
.subtask-item.sub-removing { animation: subItemRemove 0.18s var(--ease-sink) forwards; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
    .subtask-item.sub-adding,
    .subtask-item.sub-removing { animation: none; }
}

/* Subtask drag handle — matches task-level IC.drag pattern */
.sub-drag-handle {
    width: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    color: var(--text-muted);
    flex-shrink: 0;
    transition: width 0.16s ease, opacity 0.16s ease;
    pointer-events: none;
}
.subtask-item:not(.checked):not(.cycle-checked):hover .sub-drag-handle {
    width: 14px;
    /* Balance the gap to the priority stripe (left) vs the next control (right):
       +margin-left moves it off the stripe, equal -margin-right trims the flex
       gap, so spacing is symmetric and the row's overall shift is unchanged. */
    margin-left: 2px;
    margin-right: -2px;
    opacity: 0.62;
    pointer-events: auto;
}
.sub-drag-handle svg { width: 13px; height: 13px; flex-shrink: 0; }

/* Subtask drag-handle visibility is controlled by the hover rules above */

.sub-text {
    flex: 1;
    font-size: 14px;
    color: var(--text-primary);
    line-height: 1.4;
    word-break: break-word;
    min-width: 0;
}
.sub-text[contenteditable="true"] {
    outline: none;
    border-bottom: 1px dashed var(--accent);
    user-select: text;
    -webkit-user-select: text;
    cursor: text;  /* override parent cursor:grab during inline edit */
}
/* Double-click to edit hint — mirrors the main task-text interaction affordance */
.sub-text:not([contenteditable="true"]):hover {
    text-decoration: underline;
    text-decoration-style: dotted;
    text-decoration-color: rgba(140, 80, 240, 0.40);
    text-underline-offset: 2px;
    cursor: text;
}

.sub-prio-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--border-mid);
    transition: background var(--transition), box-shadow var(--transition);
}
.subtask-item[data-sprio="high"]   .sub-prio-dot { background: var(--prio-high);   box-shadow: 0 0 4px rgba(220,30,70,0.5); }
.subtask-item[data-sprio="medium"] .sub-prio-dot { background: var(--prio-medium); box-shadow: 0 0 4px rgba(210,120,20,0.5); }
.subtask-item[data-sprio="low"]    .sub-prio-dot { background: var(--prio-low);    box-shadow: 0 0 4px rgba(40,200,80,0.4); }

.sub-actions {
    display: flex;
    gap: 1px;
    flex-shrink: 0;
    opacity: 0;
    transition: opacity var(--transition);
}
.subtask-item:hover .sub-actions { opacity: 1; }

/* prio-btn is now inside sub-actions — same sizing/transition as btn-sub-action */
.btn-sub-action.sub-prio-btn {
    border-radius: 50%;   /* circular to match prio-dot motif */
}
.btn-sub-action.sub-prio-btn:hover { background: var(--accent-soft); }

.btn-sub-action {
    width: 22px;
    height: 22px;
    border-radius: var(--radius-xs);
    border: none;
    background: transparent;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition);
    padding: 0;
}
.btn-sub-action svg { width: 11px; height: 11px; pointer-events: none; }
.btn-sub-action:hover { background: var(--bg-tag); color: var(--text-secondary); }
.btn-sub-action.danger:hover { background: var(--prio-high-bg); color: var(--prio-high); }

/* Sub-note collapse: grid-template-rows 0fr↔1fr — the row track itself animates
   from collapsed to its natural content height, so there is NO fixed max-height
   clip (notes of any length up to the scroll cap reveal fully) and no inline-style
   bookkeeping. .note-open is a pure class toggle driven by _openNoteWrap/_close. */
.sub-note-wrapper {
    width: 100%;
    display: grid;
    grid-template-rows: 0fr;
    position: relative;
    flex-shrink: 0;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic);
}
.sub-note-wrapper.note-open,
.subtask-section.notes-always-open .sub-note-wrapper.has-note {
    grid-template-rows: 1fr;
}
/* The inner track must have min-height:0 + overflow:hidden so 0fr truly collapses. */
.sub-note-inner {
    min-height: 0;
    overflow: hidden;
    position: relative;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.sub-note-wrapper.note-open > .sub-note-inner,
.subtask-section.notes-always-open .sub-note-wrapper.has-note > .sub-note-inner {
    opacity: 1;
}

/* ── "Always show notes" toggle button ── */
/* Appears on task hover, stays visible when active. Styled to match btn-subtask-toggle. */
.btn-sub-notes-always {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 1px 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color var(--transition), opacity var(--transition);
    opacity: 0;
    flex-shrink: 0;
}
.task-item:hover .btn-sub-notes-always { opacity: 1; }
.btn-sub-notes-always.active { opacity: 1; color: var(--accent-hover); }
.btn-sub-notes-always:hover { color: var(--accent-hover); }
.btn-sub-notes-always svg { width: 11px; height: 11px; pointer-events: none; }
.sub-note-text {
    font-size: 12px;
    font-style: italic;
    color: var(--text-secondary);
    padding: 4px 28px 4px 30px; /* left clears the filigree flourish; right clears the dagger */
    margin-top: 3px;
    line-height: 1.45;
    word-break: break-word;
    overflow-wrap: anywhere;
    cursor: text;
    min-height: 0;
    max-height: 200px;          /* long notes scroll instead of growing unbounded */
    overflow-y: auto;
    font-variant-numeric: lining-nums tabular-nums;
    /* V2 · филигранный росчерк — a delicate gothic vine running down the left margin.
       One full sine period per 14px tile (x returns to centre at 0/7/14) so it tiles
       seamlessly AND a short one-line note still shows a complete wave, not a stub. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='14' viewBox='0 0 10 14'%3E%3Cpath d='M5 0 C1 3 9 5 5 7 C1 9 9 11 5 14' fill='none' stroke='%23a060ff' stroke-width='1.2' stroke-opacity='0.7' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: repeat-y;
    background-position: left 5px top 2px;
    background-size: 10px 14px;
}
/* While editing/creating: keep the SAME V2 flourish (consistent design in every
   state) — only enable text selection and suppress the focus outline. */
.sub-note-text.editing {
    outline: none;
    user-select: text;
    -webkit-user-select: text;
}
/* Placeholder for an empty note field (shown during the create flow). */
.sub-note-text:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
    font-style: italic;
    opacity: 0.75;
    pointer-events: none;
}
/* Auto-linkified URLs (display-only; raw text returns on edit). */
.note-link { color: var(--accent-hover); text-decoration: underline; text-underline-offset: 2px; }
.note-link:hover { color: var(--accent); }
/* Unobtrusive char counter, shown only near the limit. */
.sub-note-count {
    position: absolute;
    right: 6px;
    bottom: 2px;
    font-size: 9px;
    font-style: normal;
    color: var(--text-muted);
    opacity: 0.7;
    pointer-events: none;
    background: var(--bg-item);
    padding: 0 2px;
    border-radius: 3px;
}

/* P8: sub-note delete button — same system as btn-note-delete, proportionally smaller */
.btn-sub-note-delete {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 15px;
    height: 15px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition);
    padding: 0;
    flex-shrink: 0;
    margin-top: 1px; /* visual centre correction for 3px top margin on sub-note-text */
}
.btn-sub-note-delete svg { width: 9px; height: 9px; pointer-events: none; }
.btn-sub-note-delete:hover { background: var(--prio-high-bg); color: var(--prio-high); }

/* P4: Suppress browser focus-visible ring on ALL note/input fields.
   Each field communicates focus via its own border-color transition.
   !important needed to override the global :focus-visible rule above. */
.task-note-text:focus-visible,
.sub-note-text:focus-visible,
[contenteditable="true"]:focus-visible,
.sub-text[contenteditable="true"]:focus-visible,
.subtask-add-input:focus-visible,
.form-sub-input:focus-visible,
.inline-note-input:focus-visible,
.note-input:focus-visible,
.modal-input:focus-visible,
textarea:focus-visible {
    outline: none !important;
    box-shadow: none !important;
}

.btn-sub-action.sub-repeat-btn svg { opacity: 0.45; }
.btn-sub-action.sub-repeat-btn:hover svg { opacity: 1; }
.btn-sub-action.sub-repeat-btn.active { color: var(--accent-hover); }
.btn-sub-action.sub-repeat-btn.active svg { opacity: 1; }

/* ── P-E: subtask deadline ──────────────────────────────────────────────────
   "Set" button lives in .sub-actions when no deadline (muted, like the repeat
   button). When a deadline IS set, the button is replaced by an always-visible
   status glyph in the row (colour/pulse = status, tooltip = full date) plus a
   countdown pill that reveals on hover below the row — the same grid-rows reveal
   family as the subtask note, so the two read as one visual language. */
.btn-sub-action.sub-deadline-btn svg { opacity: 0.45; }
.btn-sub-action.sub-deadline-btn:hover svg { opacity: 1; }

/* Always-visible status glyph (IC.window) in the main row */
.sub-deadline-badge {
    flex-shrink: 0;
    width: 18px; height: 18px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: var(--radius-xs);
    transition: color var(--transition), background var(--transition);
}
.sub-deadline-badge svg { width: 12px; height: 12px; pointer-events: none; }
.sub-deadline-badge:hover { background: var(--bg-tag); color: var(--text-secondary); }
/* status colours mirror the task .deadline-tag palette */
.sub-deadline-badge.sub-dl-warn     { color: var(--deadline-warn); }
.sub-deadline-badge.sub-dl-urgent   { color: var(--deadline-urgent); }
.sub-deadline-badge.sub-dl-over     { color: var(--deadline-over); }
.sub-deadline-badge.sub-dl-critical {
    color: var(--deadline-critical);
    border-radius: 50%;
    animation: pulseCritical 1.6s ease infinite;
}

/* Hover-reveal countdown pill — grid-rows 0fr↔1fr, identical model to .sub-note-wrapper */
.sub-deadline-wrapper {
    width: 100%;
    display: grid;
    grid-template-rows: 0fr;
    flex-shrink: 0;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic);
}
.subtask-item:hover .sub-deadline-wrapper { grid-template-rows: 1fr; }
.sub-deadline-inner {
    min-height: 0;
    overflow: hidden;
    opacity: 0;
    padding-left: 30px;            /* align under text, clear of the check column */
    transition: opacity 0.18s ease;
}
.subtask-item:hover .sub-deadline-inner { opacity: 1; }
.sub-dl-pill {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    margin-top: 3px;
    padding: 2px 8px;
    border-radius: 99px;
    font-family: var(--font-label);
    background: var(--bg-tag);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    white-space: nowrap;
    cursor: pointer;
}
.sub-dl-pill:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(130, 50, 230, 0.4); }
.sub-dl-countdown { font-size: 10.5px; font-weight: 700; }
.sub-dl-date      { font-size: 9.5px; opacity: 0.80; }
.sub-dl-sep       { opacity: 0.35; font-size: 9px; align-self: center; }
/* pill status colours mirror the task .deadline-tag palette */
.sub-deadline-wrapper.sub-dl-warn     .sub-dl-pill { background: var(--deadline-warn-bg);     color: var(--deadline-warn);     border-color: rgba(120, 120, 220, 0.35); }
.sub-deadline-wrapper.sub-dl-urgent   .sub-dl-pill { background: var(--deadline-urgent-bg);   color: var(--deadline-urgent);   border-color: rgba(210, 120, 20, 0.4); }
.sub-deadline-wrapper.sub-dl-critical .sub-dl-pill { background: var(--deadline-critical-bg); color: var(--deadline-critical); border-color: rgba(220, 30, 70, 0.45); }
.sub-deadline-wrapper.sub-dl-over     .sub-dl-pill { background: var(--deadline-over-bg);     color: var(--deadline-over);     border-color: rgba(170, 15, 30, 0.5); font-weight: 700; }
/* inline clear — shares the pill ink, brightens to danger on hover (tag-clear idiom) */
.sub-dl-clear {
    border: none;
    background: transparent;
    color: inherit;
    opacity: 0.5;
    cursor: pointer;
    padding: 0 0 0 3px;
    margin-left: 1px;
    display: inline-flex;
    align-items: center;
    align-self: center;
    transition: opacity var(--transition), color var(--transition);
}
.sub-dl-clear svg { width: 9px; height: 9px; pointer-events: none; }
.sub-dl-clear:hover { opacity: 1; color: var(--deadline-over); }

/* Subtask cycle-checked — mirrors main .task-item.cycle-checked exactly:
   dashed left border, no overall opacity reduction, no strikethrough,
   text slightly muted but readable. cursor: default (not not-allowed) because
   subtask DnD does not filter cycle-checked items — not-allowed would mislead. */
.subtask-item.cycle-checked {
    border-left: 2px dashed rgba(140, 60, 240, 0.55) !important;
    border-color: rgba(100, 35, 190, 0.28);
    cursor: default;
}
.subtask-item.cycle-checked:hover {
    background: rgba(30, 6, 80, 0.12);
    border-color: rgba(130, 50, 210, 0.40);
    cursor: default;
}
.subtask-item.cycle-checked .sub-text {
    color: rgba(200, 170, 240, 0.78);
    text-decoration: none;
    /* Explicitly cancel any inherited strikethrough */
    text-decoration-line: none;
}

.subtask-add-row {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 4px;
}
.subtask-add-input {
    flex: 1;
    background: rgba(8, 2, 28, 0.60);
    border: 1px dashed var(--border-mid);
    border-radius: var(--radius-sm);
    padding: 5px 10px;
    font-family: var(--font-main);
    font-size: 13px;
    color: var(--text-primary);
    outline: none;
    transition: border-color var(--transition);
}
.subtask-add-input::placeholder { color: var(--text-muted); font-style: italic; }
.subtask-add-input:focus { border-color: rgba(140,60,255,0.5); border-style: solid; }

.btn-subtask-confirm {
    width: 26px;
    height: 26px;
    border-radius: var(--radius-xs);
    border: 1px solid var(--border-mid);
    background: var(--accent-soft);
    color: var(--accent-hover);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: all var(--transition);
    padding: 0;
}
.btn-subtask-confirm svg { width: 12px; height: 12px; pointer-events: none; }
.btn-subtask-confirm:hover { background: var(--accent); color: #fff; }

/* ===== P5: form action row — pin toggle + save-as-template ===== */
.form-action-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.form-flag-toggle,
.form-tpl-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 13px;
    border-radius: 99px;
    border: 1px solid var(--border);
    background: var(--bg-input);
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 1px;
    cursor: pointer;
    transition: all var(--transition);
}
.form-flag-toggle svg,
.form-tpl-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
.form-flag-toggle:hover,
.form-tpl-btn:hover { border-color: var(--border-mid); color: var(--text-primary); }
/* Pin toggle ON — lit accent + soft glow, mirroring the in-task pin button. */
.form-flag-toggle.active {
    background: var(--accent-soft);
    color: var(--accent-hover);
    border-color: rgba(140, 60, 255, 0.45);
    font-weight: 600;
    box-shadow: 0 0 10px -2px rgba(140, 60, 255, 0.45);
}
.form-flag-toggle.active svg { filter: drop-shadow(0 0 4px rgba(160, 96, 255, 0.6)); }
/* Save-as-template sits at the far right; hover leans into the accent. */
.form-tpl-btn { margin-left: auto; }
.form-tpl-btn:hover { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.4); }

/* ===== FORM SUBTASKS (pre-task creation) ===== */
.form-subs-section {
    margin-top: 10px;
}
.form-sub-add-row {
    display: flex;
    gap: 6px;
    align-items: center;
}
.form-sub-input {
    flex: 1;
    background: var(--bg-input);
    border: 1px dashed rgba(130, 50, 220, 0.38);
    border-radius: var(--radius-sm);
    padding: 7px 11px;
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 14px;
    outline: none;
    transition: border-color var(--transition);
}
.form-sub-input::placeholder { color: var(--text-muted); font-style: italic; }
.form-sub-input:focus { border-color: rgba(150, 70, 255, 0.55); border-style: solid; }
.form-sub-input.shake { animation: shake 0.4s ease; }
.btn-form-sub-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--accent);
    cursor: pointer;
    transition: all var(--transition);
    flex-shrink: 0;
    padding: 0;
}
.btn-form-sub-add svg { width: 13px; height: 13px; pointer-events: none; }
.btn-form-sub-add:hover { background: var(--accent); color: #000; }

/* P12: full parity with in-task subtasks — the form list now renders real
   .subtask-item rows (same global styles), laid out in the same 2-column grid
   (single column on mobile). minmax(0,1fr) so a wide item never clips its edge. */
#form-sub-list {
    list-style: none;
    margin: 6px 0 0;
    padding: 0 2px 0 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3px;
}
#form-sub-list:empty { display: none; }
/* A lone item on the final (odd) row stretches full width instead of half. */
#form-sub-list > .subtask-item:last-child:nth-child(odd) { grid-column: 1 / -1; }

.btn-subtask-toggle {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 11px;
    cursor: pointer;
    padding: 1px 0;
    font-family: var(--font-label);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: color var(--transition);
    letter-spacing: 0.5px;
    white-space: nowrap;
    flex-shrink: 0;
}
.btn-subtask-toggle:hover { color: var(--accent-hover); }
.btn-subtask-toggle svg { width: 11px; height: 11px; flex-shrink: 0; transition: transform var(--transition); pointer-events: none; }
.btn-subtask-toggle.open svg { transform: rotate(180deg); }
.btn-subtask-toggle span { white-space: nowrap; }

/* ===== TASK CONTENT ===== */
.task-content { flex: 1; min-width: 0; }
/* Problem 3: title + action buttons share the top row; everything below it
   (the meta tags + note/subtask toggles) then spans the FULL content width and
   is no longer squeezed/pushed by the right-hand action buttons. */
.task-head {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.task-head > .task-text { flex: 1; min-width: 0; }
.task-head > .task-actions { margin-top: 1px; }
.task-text {
    font-size: 16px;
    color: var(--text-primary);
    line-height: 1.55;
    display: block;
    word-break: break-word;
    transition: color var(--transition);
    font-weight: 400;
    cursor: text;
}
/* Subtle dotted underline on hover — hints that double-click opens edit (matches sub-text pattern) */
.task-text:not([contenteditable="true"]):hover {
    text-decoration: underline;
    text-decoration-style: dotted;
    text-decoration-color: rgba(140, 80, 240, 0.35);
    text-underline-offset: 3px;
}
.task-item.checked .task-text {
    color: rgba(160, 120, 210, 0.72);
    text-decoration: line-through;
    text-decoration-color: rgba(130, 80, 190, 0.52);
    text-decoration-thickness: 1.5px;
    animation: strikeColorIn 0.32s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes strikeColorIn {
    from { text-decoration-color: transparent; color: var(--text-primary); }
    to   { text-decoration-color: rgba(130, 80, 190, 0.52); color: rgba(160, 120, 210, 0.72); }
}

@media (prefers-reduced-motion: reduce) {
    .task-item.checked .task-text {
        animation: none;
    }
}
.task-text[contenteditable="true"] {
    outline: none;
    border-bottom: 1px dashed var(--accent);
    padding-bottom: 1px;
    cursor: text;
    user-select: text;
    -webkit-user-select: text;
}

/* Meta tags row */
.task-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    margin-top: 5px;
}

.meta-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    color: var(--text-secondary);
    background: var(--bg-tag);
    padding: 2px 8px;
    border-radius: 99px;
    font-weight: 500;
    border: 1px solid var(--border);
    font-family: var(--font-label);
    white-space: nowrap;
}
.meta-tag svg { width: 9px; height: 9px; }

/* Deadline in one line */
/* baseline (not center): countdown 10.5px and absolute 9.5px are different
   sizes — centring them made the date sit visibly higher than the counter.
   Sharing a baseline makes them read as one line. */
.dl-badge-inner { display: flex; flex-direction: row; align-items: baseline; gap: 4px; white-space: nowrap; }
.dl-countdown { font-size: 10.5px; font-weight: 700; }
.dl-absolute  { font-size: 9.5px; opacity: 0.80; }
.dl-sep { opacity: 0.35; font-size: 9px; }

/* Deadline status colors */
.deadline-tag.warn     { background: var(--deadline-warn-bg);     color: var(--deadline-warn);     border-color: rgba(120, 120, 220, 0.35); }
.deadline-tag.urgent   { background: var(--deadline-urgent-bg);   color: var(--deadline-urgent);   border-color: rgba(210, 120, 20, 0.4); }
.deadline-tag.critical {
    background: var(--deadline-critical-bg);
    color: var(--deadline-critical);
    border-color: rgba(220, 30, 70, 0.45);
    /* #3: the pulse box-shadow lives on .meta-tag-wrap (the actual pill, which also
       holds the clear button) so the glow ring encircles the WHOLE pill, not just
       the inner tag. Synced in phase by _syncCriticalPulse(). */
}
.deadline-tag.over { background: var(--deadline-over-bg); color: var(--deadline-over); border-color: rgba(170, 15, 30, 0.5); font-weight: 700; }

@keyframes pulseCritical {
    0%, 100% { box-shadow: none; }
    50%       { box-shadow: 0 0 0 3px rgba(220, 30, 70, 0.22), 0 0 12px rgba(220, 30, 70, 0.15); }
}

/* X-7: «идёт сейчас» — event in progress. Steady luminous violet glow (an active
   ritual), deliberately distinct from critical's red urgency pulse. */
.deadline-tag.live {
    background: var(--accent-soft);
    color: var(--accent-hover);
    border-color: rgba(150, 70, 255, 0.5);
    /* #3: pulse glow lives on .meta-tag-wrap (whole pill incl. clear button). */
}
@keyframes pulseLive {
    0%, 100% { box-shadow: 0 0 0 1px rgba(150, 70, 255, 0.22), 0 0 6px rgba(150, 70, 255, 0.16); }
    50%      { box-shadow: 0 0 0 3px rgba(150, 70, 255, 0.34), 0 0 16px rgba(150, 70, 255, 0.30); }
}
.meta-tag-wrap:has(> .deadline-tag.live)   { background: var(--accent-soft); border-color: rgba(150, 70, 255, 0.45); animation: pulseLive 2.4s var(--ease-gothic) infinite; }
.meta-tag-wrap:has(> .deadline-tag.live) .btn-tag-clear { color: var(--accent-hover); }
/* schedule-mode side panel + subtask variants of the live state */
.dl-side-panel.dl-side-live { border-right-color: var(--accent-hover); }
.dl-side-panel.dl-side-live .dl-side-countdown { color: var(--accent-hover); }
.sub-deadline-badge.sub-dl-live { color: var(--accent-hover); }
.sub-deadline-wrapper.sub-dl-live .sub-dl-pill {
    background: var(--accent-soft); color: var(--accent-hover); border-color: rgba(150, 70, 255, 0.4);
}
@media (prefers-reduced-motion: reduce) {
    .meta-tag-wrap:has(> .deadline-tag.live),
    .meta-tag-wrap:has(> .deadline-tag.critical) { animation: none; }
}

.repeat-tag { color: var(--accent-hover); background: var(--accent-soft); border-color: rgba(130, 50, 230, 0.35); }


/* ── Tag inline clear button ─────────────────────────────────────────────
   DESIGN (problem 3): the WRAP is the pill — it carries the background, border
   and radius. The tag content and the slide-out clear button sit inside it with
   NO background/border of their own, so there is a single continuous fill: the
   button is literally part of the tag body (no seam, no translucent-overlap line
   between two separately-painted boxes).                                         */
.meta-tag-wrap {
    display: inline-flex;
    align-items: stretch;
    vertical-align: middle;
    position: relative;
    border: 1px solid var(--border);
    border-radius: 99px;
    background: var(--bg-tag);
}
/* Inside a wrap the tag paints nothing — the wrap is the pill. (Standalone
   .meta-tag elsewhere keep their own bg/border; only wrapped ones are stripped.) */
/* Inside a wrap the tag paints nothing — the wrap is the pill. Its padding is
   CONSTANT (never animated) — that is what kept biting us. */
.meta-tag-wrap > .meta-tag {
    margin: 0;
    background: transparent;
    border: none;
}

/* ── ✕ reveal, rebuilt from scratch ──────────────────────────────────────────
   The bounce came from the icon MOVING horizontally during the reveal (first a
   -3px margin pull, then a collapsing text padding — both shoved the icon left
   while the width grew it right → "hits a wall and returns"). Centring it in a
   growing box also slid it sideways.

   New mechanism: the icon NEVER moves. It is pinned to the button's left edge
   (justify-content:flex-start), and the button's left edge is fixed (the tag's
   padding is constant). Growing the button's width just slides the overflow clip
   window rightward, wiping the stationary icon into view; opacity fades it in on
   the same curve. Nothing competes, nothing animates but width+opacity → no
   bounce, no snap, fully smooth. */
.btn-tag-clear {
    display: flex;
    align-items: center;
    justify-content: flex-start;   /* pin icon left → it stays put while revealed */
    width: 0;
    min-width: 0;
    overflow: hidden;
    padding: 0;
    border: none;
    cursor: pointer;
    opacity: 0;
    flex-shrink: 0;
    background: transparent;          /* the wrap's fill shows through — seamless */
    color: var(--text-muted);
    white-space: nowrap;
    /* ASYMMETRIC timing. The transition declared HERE (base state) governs the
       HIDE (hover→base): quick & brisk so it doesn't linger. The reveal is
       governed by the longer, gentler curve on the :hover/:focus rule below. */
    transition: width 0.32s ease, opacity 0.32s ease;
}
.btn-tag-clear svg { width: 8px; height: 8px; pointer-events: none; flex-shrink: 0; }

/* width 16px = icon(8) pinned left + 8px of trailing space. The text→icon gap is
   the tag's constant 8px right padding; icon→pill-edge is the 8px button tail →
   equal 8px gaps on both sides, identical in every pill variant. Keyboard focus
   reveals it too. */
.meta-tag-wrap:hover .btn-tag-clear,
.meta-tag-wrap:focus-within .btn-tag-clear {
    width: 16px;
    /* NB: do NOT set min-width here. min-width isn't transitionable, so a
       min-width:16px would clamp the used width to 16 on the very first frame
       and the width animation would never be seen (instant reveal). Base keeps
       min-width:0 so the width transition actually drives the open. */
    opacity: 1;
    /* Transition declared HERE governs the REVEAL (base→hover): fast but clearly
       visible, gently eased so it opens smoothly rather than snapping. The hide
       uses the brisk base transition above. */
    transition: width 0.4s cubic-bezier(0.2, 0, 0.2, 1),
                opacity 0.4s cubic-bezier(0.2, 0, 0.2, 1);
}
/* High enough specificity (0,4,0) to beat the per-variant base-colour rules
   below — otherwise the repeat pill's accent-hover override kept the ✕ purple on
   hover while the deadline pill (no such override) went red. */
.meta-tag-wrap:hover .btn-tag-clear:hover,
.meta-tag-wrap:focus-within .btn-tag-clear:focus-visible { color: #e06070; }

/* Per-variant pill background + border live on the WRAP so the whole pill
   (tag body + revealed button) is one uniform colour. Button keeps the matching
   icon colour only. */
.meta-tag-wrap:has(> .repeat-tag)            { background: var(--accent-soft);        border-color: rgba(130, 50, 230, 0.35); }
.meta-tag-wrap:has(> .repeat-tag) .btn-tag-clear { color: var(--accent-hover); }
.meta-tag-wrap:has(> .deadline-tag)          { background: var(--bg-tag);             border-color: var(--border); }
.meta-tag-wrap:has(> .deadline-tag.warn)     { background: var(--deadline-warn-bg);     border-color: rgba(120, 120, 220, 0.35); }
.meta-tag-wrap:has(> .deadline-tag.warn) .btn-tag-clear     { color: var(--deadline-warn); }
.meta-tag-wrap:has(> .deadline-tag.urgent)   { background: var(--deadline-urgent-bg);   border-color: rgba(210, 120, 20, 0.4); }
.meta-tag-wrap:has(> .deadline-tag.urgent) .btn-tag-clear   { color: var(--deadline-urgent); }
.meta-tag-wrap:has(> .deadline-tag.critical) { background: var(--deadline-critical-bg); border-color: rgba(220, 30, 70, 0.45); animation: pulseCritical 1.6s ease infinite; }
.meta-tag-wrap:has(> .deadline-tag.critical) .btn-tag-clear { color: var(--deadline-critical); }
.meta-tag-wrap:has(> .deadline-tag.over)     { background: var(--deadline-over-bg);     border-color: rgba(170, 15, 30, 0.5); }
.meta-tag-wrap:has(> .deadline-tag.over) .btn-tag-clear     { color: var(--deadline-over); }
/* Brighten the ✕ to danger on hover for EVERY deadline variant. Must come after
   the per-variant base-colour rules AND outrank them: specificity (0,5,0) here vs
   (0,4,0) above, so it wins on hover regardless of status (warn/urgent/etc kept the
   ✕ tinted on hover before this). Mirrors the subtask pill clear hover. */
.meta-tag-wrap:has(> .deadline-tag):hover .btn-tag-clear:hover,
.meta-tag-wrap:has(> .deadline-tag):focus-within .btn-tag-clear:focus-visible { color: #e06070; }

/* Persistent "done until …" label for cycle-completed recurring tasks.
   Violet-purple tint — matches the project's gothic palette exactly.
   Italic text + subtle glow border makes it distinct from deadline (red/orange)
   and repeat-type (plain violet) tags without introducing alien colours. */
.cycle-until-tag {
    color: rgba(215, 175, 255, 0.90);
    background: rgba(80, 20, 180, 0.18);
    border-color: rgba(140, 60, 240, 0.38);
    font-style: italic;
    letter-spacing: 0.15px;
}
.group-tag  { font-style: italic; }
.muted-tag  { opacity: 0.55; }

/* Hashtag */
.hashtag { color: var(--accent-hover); cursor: pointer; font-weight: 600; font-family: inherit; }
.hashtag:hover { text-decoration: underline; text-shadow: 0 0 8px var(--accent-glow); }

/* ── Tag cloud (renders below search bar) ─────────────────────────────────── */
.tag-cloud {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    padding: 4px 0 2px;
    animation: tagCloudIn 0.18s var(--ease-gothic) both;
}
@keyframes tagCloudIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px;
    border-radius: 99px;
    border: 1px solid var(--border);
    background: var(--bg-item);
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 9.5px;
    letter-spacing: 0.7px;
    cursor: pointer;
    transition: all var(--transition);
}
.tag-chip:hover {
    border-color: var(--accent-hover);
    color: var(--accent-hover);
    background: rgba(100, 30, 200, 0.1);
    box-shadow: 0 0 8px rgba(130, 50, 255, 0.18);
}
.tag-chip.active {
    border-color: rgba(180, 90, 255, 0.7);
    color: rgba(200, 130, 255, 0.95);
    background: rgba(100, 30, 200, 0.18);
    box-shadow: 0 0 10px rgba(140, 50, 255, 0.22);
}
.tag-chip-count {
    opacity: 0.55;
    font-size: 8.5px;
    font-weight: 700;
}

/* Note */
/* Smooth collapse via grid-template-rows 0fr↔1fr (same model as .sub-note-wrapper):
   the row track animates from collapsed to its natural content height — no fixed
   max-height clip and no janky easing against a 600px cap. The wrapper is always
   in the DOM (even note-less), so the margin lives on .visible to avoid a phantom
   gap under note-less tasks. */
.task-note-wrapper {
    position: relative;
    display: grid;
    grid-template-rows: 0fr;
    margin-top: 0;
    /* full-width fill of .task-content — no negative-margin break-out. */
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic),
                margin-top var(--dur-collapse) var(--ease-gothic);
}
.task-note-wrapper.visible {
    grid-template-rows: 1fr;
    margin-top: 7px;
}
/* The inner track needs min-height:0 + overflow:hidden so 0fr truly collapses. */
.task-note-inner {
    min-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: opacity 0.2s var(--ease-gothic);
}
.task-note-wrapper.visible > .task-note-inner { opacity: 1; }

/* Task note — variant A "illuminated page": a warm parchment tint over the dark
   panel, a gothic corner fleuron top-left and an accent drop-cap initial, plus
   auto-grow + internal scroll. Deliberately distinct from the subtask V2 vine. */
.task-note-text {
    position: relative;
    font-size: 14px;
    font-style: italic;
    color: var(--text-secondary);
    line-height: 1.55;
    padding: 9px 38px 9px 46px;   /* left clears the corner fleuron */
    border-radius: var(--radius-sm);
    border-left: 2px solid var(--border-mid);
    cursor: text;
    transition: border-color var(--transition);
    word-break: break-word;
    overflow-wrap: anywhere;
    white-space: pre-wrap;        /* honour Shift+Enter line breaks */
    display: block;
    min-height: 0;
    max-height: 320px;           /* long notes scroll instead of growing unbounded */
    overflow-y: auto;
    user-select: text;
    -webkit-user-select: text;
    /* Cormorant Garamond italic uses old-style numerals which descend below baseline;
       lining-nums keeps 1–9 on the baseline even in italic weight. */
    font-variant-numeric: lining-nums tabular-nums;
    background-color: var(--bg-input);
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32' fill='none' stroke='%23a060ff' stroke-width='1.4' stroke-linecap='round'%3E%3Cpath d='M4 28 C4 14 14 4 28 4' stroke-opacity='0.5'/%3E%3Cpath d='M4 28 C10 24 12 18 12 12 C18 12 24 8 26 4' stroke-opacity='0.3'/%3E%3Ccircle cx='28' cy='4' r='1.5' fill='%23a060ff' fill-opacity='0.55' stroke='none'/%3E%3Ccircle cx='4' cy='28' r='1.5' fill='%23a060ff' fill-opacity='0.55' stroke='none'/%3E%3C/svg%3E"),
        linear-gradient(180deg, rgba(120, 86, 40, 0.10), rgba(70, 48, 22, 0.035));
    background-repeat: no-repeat, no-repeat;
    background-position: left 11px top 9px, center;
    background-size: 26px 26px, auto;
}
.task-note-text.editing { outline: none; border-left-color: var(--accent); cursor: text; }
.task-note-text:hover:not(.editing) { border-left-color: var(--border-bright); }
/* Placeholder shown while the note field is empty (create flow). */
.task-note-text:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
    font-style: italic;
    opacity: 0.78;
    pointer-events: none;
}
/* Unobtrusive char counter, shown only near the limit. */
.task-note-count {
    position: absolute;
    right: 12px;
    bottom: 4px;
    font-size: 10px;
    font-style: normal;
    color: var(--text-muted);
    opacity: 0.72;
    pointer-events: none;
    background: var(--bg-input);
    padding: 0 3px;
    border-radius: 3px;
}

.btn-note-delete {
    position: absolute;
    right: 14px;          /* was 6px — shifted left to clear container border */
    top: 8px;             /* top-aligned: the panel can grow tall (multiline) */
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 11px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition);
    line-height: 1;
    flex-shrink: 0;
}
.btn-note-delete svg { width: 13px; height: 13px; pointer-events: none; }
.btn-note-delete:hover { background: var(--prio-high-bg); color: var(--prio-high); }

@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }

.inline-note-input {
    width: 100%;
    background: rgba(8, 2, 28, 0.60);
    border: 1px dashed var(--border-mid);
    border-radius: var(--radius-sm);
    padding: 5px 10px;
    font-family: var(--font-main);
    font-size: 13.5px;
    font-style: italic;
    color: var(--text-primary);
    outline: none;
    transition: border-color var(--transition), border-style var(--transition);
}
.inline-note-input::placeholder { color: var(--text-muted); }
.inline-note-input:focus {
    border-color: rgba(140, 60, 255, 0.55);
    border-style: solid;
}

.btn-note-toggle {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 11px;
    cursor: pointer;
    padding: 1px 0;
    font-family: var(--font-label);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: color var(--transition);
    letter-spacing: 0.5px;
    white-space: nowrap;
    flex-shrink: 0;
}
.btn-note-toggle:hover { color: var(--accent-hover); }
.btn-note-toggle svg { width: 10px; height: 10px; flex-shrink: 0; transition: transform var(--transition); pointer-events: none; }
.btn-note-toggle.open svg { transform: rotate(180deg); }
.btn-note-toggle span { white-space: nowrap; }

/* Task actions */
.task-actions {
    display: flex;
    gap: 2px;
    align-items: flex-start;
    flex-shrink: 0;
    opacity: 0;
    transition: opacity var(--transition);
}
.task-item:hover .task-actions { opacity: 1; }
.archive-actions { opacity: 1 !important; }

.btn-task-action {
    width: 27px;
    height: 27px;
    border-radius: var(--radius-xs);
    border: none;
    background: transparent;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition);
    padding: 0;
}
.btn-task-action svg { width: 13px; height: 13px; }
.btn-task-action:hover { background: var(--bg-tag); color: var(--text-secondary); }
.btn-task-action.danger:hover { background: var(--prio-high-bg); color: var(--prio-high); }
.btn-task-action.archive-btn:hover { background: rgba(80, 15, 180, 0.25); color: var(--accent-hover); }
.restore-btn:hover { background: var(--accent-soft); color: var(--accent-hover); }
.btn-task-action.edit-note-btn { font-family: var(--font-label); font-size: 9.5px; width: auto; padding: 0 6px; letter-spacing: 0.3px; white-space: nowrap; }

/* Search highlight */
.highlight {
    background: rgba(140, 60, 255, 0.20);
    border-radius: 2px;
    color: var(--accent-hover);
    font-weight: 600;
}

/* ===== EMPTY / ALL DONE ===== */
.empty-state {
    text-align: center;
    padding: 48px 20px;
    color: var(--text-muted);
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}
.empty-rune {
    font-size: 36px;
    opacity: 0.20;
    font-family: var(--font-label);
    animation: ornamentPulse 5s ease-in-out infinite;
}
/* #4 (порт _grimEmptyHTML): CTA пустого состояния — та же готик-кнопка, что «Начертать первую». */
.empty-add-btn {
    margin-top: 6px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.28), rgba(80, 15, 180, 0.16));
    color: var(--accent-hover);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-md);
    padding: 9px 16px;
    font-family: var(--font-label);
    font-size: 11.5px;
    letter-spacing: 1px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all var(--transition);
}
.empty-add-btn:hover { border-color: var(--border-bright); box-shadow: 0 0 16px rgba(120, 40, 220, 0.28); color: var(--text-primary); }
.empty-add-btn svg { width: 14px; height: 14px; }
.empty-state p { font-size: 14px; letter-spacing: 1px; font-family: var(--font-label); opacity: 0.65; }

/* All-done: purple, not green */
.all-done {
    text-align: center;
    padding: 28px 20px;
    color: var(--accent-hover);
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}
.all-done-icon {
    font-size: 30px;
    opacity: 0.8;
    animation: allDonePop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
    filter: drop-shadow(0 0 12px rgba(180, 100, 255, 0.6));
}
.all-done p { font-size: 13px; font-weight: 600; letter-spacing: 1.5px; font-family: var(--font-label); text-transform: uppercase; }
@keyframes allDoneIcon {
    0%   { transform: scale(0.3) rotate(-45deg); opacity: 0; }
    60%  { transform: scale(1.18) rotate(8deg);  opacity: 1; }
    80%  { transform: scale(0.94) rotate(-3deg); }
    100% { transform: scale(1)    rotate(0deg);  opacity: 1; }
}
@keyframes allDoneText {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0);   }
}
@keyframes allDonePop { from { transform: scale(0.4); opacity: 0 } to { transform: scale(1); opacity: 1 } }
.todo-app.cathedral-flash { animation: cathedralFlash 1.4s ease forwards; }

/* ===== ARCHIVE PAGE ===== */
.archive-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 16px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border);
    position: relative;
}
.archive-header::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 30%; right: 30%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(140, 60, 255, 0.4), transparent);
}

.archive-btns {
    display: flex;
    align-items: center;
    gap: 5px;
    flex-wrap: wrap;
}

.archive-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-secondary);
    font-family: var(--font-title);
    letter-spacing: 2px;
    text-transform: uppercase;
}
.archive-title svg { width: 13px; height: 13px; }

/* Shared style for all archive header buttons */
.btn-archive-action {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 5px 11px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 10.5px;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap;
}
.btn-archive-action svg { width: 11px; height: 11px; flex-shrink: 0; }
.btn-archive-action:hover { border-color: var(--border-bright); color: var(--accent-hover); background: var(--accent-dim); }
.btn-archive-action.btn-select-mode.active {
    background: var(--accent-soft);
    color: var(--accent-hover);
    border-color: rgba(150, 70, 255, 0.45);
}
.btn-archive-action.btn-clear-archive:hover { border-color: var(--prio-high-border); color: var(--prio-high); background: var(--prio-high-bg); }

/* Keep old rule for compatibility */
.btn-clear-archive { /* properties now on .btn-archive-action */ }

/* Archive item states */
.archive-item { opacity: 0.75; cursor: default; }
.archive-item:hover { opacity: 1; }
.archive-item.select-mode { cursor: pointer; }
.archive-item.select-mode:hover { opacity: 1; background: var(--bg-item-hover); }
.archive-item.arc-selected {
    opacity: 1;
    border-color: rgba(150, 70, 255, 0.45) !important;
    background: rgba(80, 20, 160, 0.18) !important;
    box-shadow: 0 0 0 1px rgba(150, 70, 255, 0.20);
}

/* Selection indicator (checkbox) */
.arc-select-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    min-width: 22px;
    color: var(--text-muted);
    flex-shrink: 0;
}
.arc-select-indicator svg { width: 16px; height: 16px; display: block; }
.archive-item.arc-selected .arc-select-indicator { color: var(--accent); }

/* Bottom selection bar */
.archive-select-bar {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    margin-top: 10px;
    background: rgba(8, 3, 28, 0.97);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-md);
    box-shadow: 0 -4px 20px rgba(0,0,0,0.5), 0 0 20px rgba(80,20,160,0.15);
    backdrop-filter: blur(12px);
    z-index: 10;
}
/* Main list bulk select bar sits at top of list-wrapper, not bottom */
.main-select-bar {
    position: static;
    margin-top: 0;
    margin-bottom: 10px;
}

/* ── Task select checkbox (shown in mainSelectMode) ─────────────────────── */
.task-select-checkbox {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    flex-shrink: 0;
    padding: 0;
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--text-dim, rgba(180,140,255,0.38));
    transition: color var(--transition), transform var(--transition);
    align-self: flex-start;
    margin-top: 3px;
}
.task-select-checkbox svg { width: 20px; height: 20px; display: block; }
.task-select-checkbox.selected {
    color: rgba(200, 130, 255, 0.95);
    transform: scale(1.08);
}
.task-select-checkbox:hover { color: rgba(180, 90, 255, 0.8); }

/* Selected task row highlight */
.task-item.select-mode-selected {
    background: rgba(100, 30, 200, 0.12);
    border-color: rgba(160, 80, 255, 0.35);
}

/* Delete button variant in select bar */
.btn-select-bar-delete {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(200, 40, 60, 0.35);
    background: rgba(160, 20, 40, 0.12);
    color: var(--prio-high);
    font-family: var(--font-label);
    font-size: 10.5px;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1px;
    text-transform: uppercase;
}
.btn-select-bar-delete:not(:disabled):hover {
    background: rgba(200, 30, 50, 0.20);
    border-color: rgba(230, 60, 80, 0.55);
}
.btn-select-bar-delete:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-select-bar-delete svg { width: 14px; height: 14px; flex-shrink: 0; }
.btn-select-bar-delete.confirm-armed {
    background: rgba(200, 30, 50, 0.28);
    border-color: rgba(230, 60, 80, 0.8);
    animation: dangerPulse 0.5s ease infinite alternate;
}
.select-bar-count {
    font-family: var(--font-label);
    font-size: 11px;
    color: var(--text-muted);
    letter-spacing: 1px;
    white-space: nowrap;
}
.select-bar-actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }

/* ── Main bulk-select bar — mirrors the toolbar: a centred row of compact square
   icon-buttons in clustered groups split by hairline gothic dividers, with the
   count as a leading title. No space-between (which left a dead gap in the middle)
   and no wide text pills (which wrapped into two ragged rows). ───────────────── */
.main-select-bar {
    justify-content: center;   /* override archive bar's space-between → no centre void */
    gap: 14px;
}
.main-select-bar .select-bar-count {
    flex-shrink: 0;
    padding-right: 2px;
}
.main-select-bar .select-bar-actions {
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 0;
}
.select-bar-group { display: flex; align-items: center; gap: 6px; padding: 0 12px; position: relative; }
.select-bar-group:first-child { padding-left: 0; }
.select-bar-group + .select-bar-group::before {
    content: '';
    position: absolute;
    left: 0;
    top: 4px;
    bottom: 4px;
    width: 1px;
    background: linear-gradient(180deg, transparent, rgba(160, 80, 255, 0.32) 28%, rgba(160, 80, 255, 0.32) 72%, transparent);
}
/* Square icon button — same footprint/feel as the toolbar's .btn-tool */
.sb-btn {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background: var(--bg-input);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: color var(--transition), border-color var(--transition), background var(--transition), box-shadow var(--transition);
}
.sb-btn svg { width: 15px; height: 15px; }
.sb-btn:hover:not(:disabled) { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.5); background: var(--accent-dim); }
.sb-btn:disabled { opacity: 0.32; cursor: not-allowed; }
.sb-btn.sb-prio-none { font-family: var(--font-label); font-size: 15px; color: var(--text-muted); }
.sb-archive:hover:not(:disabled) { color: var(--accent-hover); }
.sb-delete { border-color: rgba(200, 40, 60, 0.32); color: var(--prio-high); }
.sb-delete:hover:not(:disabled) { background: rgba(200, 30, 50, 0.18); border-color: rgba(230, 60, 80, 0.55); color: var(--prio-high); }
.sb-delete.confirm-armed {
    background: rgba(200, 30, 50, 0.28);
    border-color: rgba(230, 60, 80, 0.8);
    animation: dangerPulse 0.5s ease infinite alternate;
}
.main-select-bar .btn-select-bar-cancel { margin-left: 4px; }
.btn-select-bar-cancel {
    padding: 6px 13px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 10.5px;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1px;
    text-transform: uppercase;
}
.btn-select-bar-cancel:hover { background: var(--bg-input); border-color: var(--border-bright); }
.btn-select-bar-restore {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(140, 60, 255, 0.40);
    background: var(--accent-soft);
    color: var(--accent-hover);
    font-family: var(--font-label);
    font-size: 10.5px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap; /* keep multi-word labels ("В архив") on one line so the button never grows taller than its row-mates */
}
.btn-select-bar-restore svg { width: 11px; height: 11px; flex-shrink: 0; }
.btn-select-bar-restore:hover:not(:disabled) { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 0 12px rgba(140,60,255,0.3); }
.btn-select-bar-restore:disabled { opacity: 0.35; cursor: not-allowed; }

/* ===== MODAL ===== */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: var(--bg-overlay);
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    animation: overlayIn var(--dur-quick) ease;
    backdrop-filter: blur(6px);
}
.modal-overlay.closing {
    animation: overlayOut var(--dur-quick) ease forwards;
    pointer-events: none;
}

.modal {
    background: var(--bg-modal);
    border-radius: var(--radius-lg);
    padding: 24px 26px;
    width: 370px;
    max-width: calc(100vw - 28px);
    box-shadow: var(--shadow-lg), 0 0 50px rgba(80, 0, 180, 0.22);
    border: 1px solid var(--border-mid);
    animation: modalIn var(--dur-standard) var(--ease-emerge);
    position: relative;
    backdrop-filter: blur(16px);
}
.modal-overlay.closing .modal {
    animation: modalOut var(--dur-quick) var(--ease-sink) forwards;
}
.modal::before {
    content: '';
    position: absolute;
    top: 0;
    left: 15%; right: 15%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(200, 100, 255, 0.6), transparent);
}

.modal-small   { width: 310px; }
.modal-deadline { width: 440px; }
.modal-note    { width: 390px; }

@keyframes modalIn {
    from { opacity: 0; transform: scale(0.93) translateY(10px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

.modal-title {
    font-size: 14px;
    font-weight: 700;
    margin-bottom: 18px;
    color: var(--text-primary);
    letter-spacing: 2px;
    font-family: var(--font-title);
    text-transform: uppercase;
}

.modal-row { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }

.modal-input {
    width: 100%;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    outline: none;
    transition: border-color var(--transition);
}
.modal-input:focus { border-color: rgba(150, 70, 255, 0.55); }
.modal-input option { background: #060218; }

.modal-textarea {
    width: 100%;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    outline: none;
    resize: vertical;
    transition: border-color var(--transition);
    margin-bottom: 14px;
    font-variant-numeric: lining-nums tabular-nums;
}
.modal-textarea::placeholder { color: var(--text-muted); font-style: italic; }
.modal-textarea:focus { border-color: rgba(150, 70, 255, 0.55); }

.color-swatch {
    width: 27px;
    height: 27px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    transition: transform var(--transition), border-color var(--transition);
    padding: 0;
}
.color-swatch:hover { transform: scale(1.2); }
.color-swatch.active { border-color: rgba(255, 255, 255, 0.7); transform: scale(1.12); box-shadow: 0 0 10px currentColor; }

/* Form color picker — compact row in extra-fields */
.field-color-form { min-width: 0; }
.form-color-picker {
    /* Fixed 6-column grid → a symmetric 6×2 block (10 presets + "без цвета" + the
       custom-spectrum crystal), instead of a ragged wrapping flex row. */
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 9px 6px;
    justify-items: center;
    align-items: center;
    padding: 4px 0 2px;
}
.form-color-swatch {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    flex-shrink: 0;
    transition: transform var(--transition), border-color var(--transition), box-shadow var(--transition);
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    background: var(--bg-item);
}
.form-color-swatch[data-color=""] {
    background: var(--bg-item);
    border-color: var(--border);
}
.form-color-swatch:hover { transform: scale(1.18); }
.form-color-swatch.active {
    border-color: rgba(255, 255, 255, 0.7);
    transform: scale(1.12);
    box-shadow: 0 0 8px rgba(255,255,255,0.25);
}
.form-color-swatch[data-color=""].active {
    border-color: var(--accent-hover);
    box-shadow: 0 0 6px rgba(160, 80, 255, 0.35);
    color: var(--accent-hover);
}
/* Custom-spectrum crystal — opens the colour modal; matches a swatch's footprint.
   Default: a clean violet crystal glyph on dark (the "open spectrum" affordance).
   When a custom colour is chosen, the button fills with that colour like a preset
   swatch (glyph hidden, white selection ring) so the pick reads clearly. */
.form-color-custom {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid var(--border-mid);
    background: var(--bg-item);
    color: var(--accent);
    cursor: pointer;
    flex-shrink: 0;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform var(--transition), border-color var(--transition), box-shadow var(--transition), color var(--transition);
}
.form-color-custom svg { display: block; }
.form-color-custom:hover { transform: scale(1.18); color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.6); }
.form-color-custom.has-color {
    border-color: rgba(255, 255, 255, 0.7);
    transform: scale(1.12);
    box-shadow: 0 0 8px rgba(255, 255, 255, 0.25);
}
.form-color-custom.has-color svg { display: none; }

/* P6 + P-fix#2: group colour block — 10 presets (reuse .task-color-picker grid) +
   the full gothic spectrum embedded directly (markup in index.html reuses .gothic-rgb;
   the group copy has no Apply/Clear — drag = live group colour). */
.group-color-block { padding: 2px 0 4px; }
.gothic-rgb-group { margin-top: 0; }

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    flex-wrap: wrap;
}

.btn-modal-cancel {
    padding: 7px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 11.5px;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1.5px;
    text-transform: uppercase;
}
.btn-modal-cancel:hover { background: var(--bg-input); border-color: var(--border-bright); color: var(--text-primary); }
/* "Без цвета" — same weight/brightness as Отмена, with a gothic ⊘ glyph; sits in the
   colour modal's action row so the modal has no dangling empty space below the spectrum. */
.btn-modal-clear { display: inline-flex; align-items: center; gap: 7px; }
.btn-modal-clear svg { width: 14px; height: 14px; flex-shrink: 0; }
.modal-color .modal-actions { justify-content: flex-end; margin-top: 14px; }

.btn-modal-danger {
    padding: 7px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--prio-high-border);
    background: var(--prio-high-bg);
    color: var(--prio-high);
    font-family: var(--font-label);
    font-size: 11.5px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1.5px;
    text-transform: uppercase;
}
/* NA-3: «Заменить» had no hover state (cancel/confirm did) — it read as dead next
   to them. Intensify the danger red on hover, mirroring the confirm-button glow. */
.btn-modal-danger:not(.btn-dl-clear):hover {
    background: rgba(180, 20, 55, 0.55);
    border-color: var(--prio-high);
    color: #fff;
    box-shadow: 0 0 13px rgba(230, 60, 80, 0.35);
}
/* Deadline clear button — icon-only variant of btn-modal-danger */
.btn-modal-danger.btn-dl-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    padding: 0 14px;
    min-width: 44px;
}
.btn-modal-danger.btn-dl-clear svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}



.btn-modal-confirm {
    padding: 7px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(140, 60, 255, 0.40);
    background: var(--accent-soft);
    color: var(--accent-hover);
    font-family: var(--font-label);
    font-size: 11.5px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1.5px;
    text-transform: uppercase;
}
.btn-modal-confirm:hover { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 0 14px rgba(140, 60, 255, 0.3); }

/* Deadline modal */
.dl-mode-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 5px;
    margin-bottom: 16px;
}
.dl-mode-btn {
    padding: 8px 6px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg-input);
    color: var(--text-secondary);
    font-family: var(--font-label);
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition);
    text-align: center;
    white-space: nowrap;
    line-height: 1.3;
    letter-spacing: 1.5px;
    text-transform: uppercase;
}
.dl-mode-btn:hover { border-color: var(--border-mid); color: var(--text-primary); }
.dl-mode-btn.active {
    background: var(--accent-soft);
    color: var(--accent-hover);
    border-color: rgba(140, 60, 255, 0.40);
    font-weight: 600;
}

.dl-inputs { margin-bottom: 16px; min-height: 44px; }
.dl-input-wrap { display: none; }
.dl-input-wrap.active { display: block; }

.weektime-row { display: flex; gap: 8px; align-items: center; }
.weektime-row .modal-input { flex: 1; }
/* Match time-input height to gothic weekday trigger button (~41px natural height) */
.weektime-row input[type="time"].modal-input {
    box-sizing: border-box;
    height: 41px;
    flex: 1;
}

.dl-hint { font-size: 11px; color: var(--text-secondary); margin-top: 7px; font-style: italic; font-family: var(--font-label); }

/* X-6: auto-weekly toggle inside the «День + Время» deadline section. Default ON
   (a weekday deadline implies the task recurs each week); off = one-shot mode.
   «Лунный круг» glyph + two-line label + lunar-phase switch — state driven by .on,
   ON-lit but deliberately restrained (не кричит). */
.dl-repeat-toggle {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    margin-top: 11px;
    padding: 10px 13px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: linear-gradient(180deg, rgba(14, 5, 38, 0.5), rgba(7, 3, 22, 0.5));
    color: var(--text-secondary);
    cursor: pointer;
    text-align: left;
    transition: border-color var(--dur-standard) var(--ease-gothic), background var(--dur-standard) var(--ease-gothic);
}
.dl-repeat-toggle:hover { border-color: var(--border-mid); }
.dl-repeat-toggle[hidden] { display: none; }   /* class sets display:flex → need explicit hide */

/* glyph — лунный круг */
.dl-repeat-toggle .dl-rt-glyph {
    width: 30px; height: 30px; flex: 0 0 30px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--text-secondary);
    transition: color var(--dur-standard) var(--ease-gothic), filter var(--dur-standard) var(--ease-gothic), transform var(--dur-ritual) var(--ease-gothic);
}
.dl-repeat-toggle .dl-rt-glyph svg { width: 30px; height: 30px; display: block; overflow: visible; }

/* two-line label, neatly stacked & left-aligned */
.dl-repeat-toggle .dl-rt-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.dl-repeat-toggle .dl-rt-title {
    font-family: var(--font-label);
    font-size: 11px; font-weight: 600; letter-spacing: 1.4px; text-transform: uppercase;
    color: var(--text-secondary);
    transition: color var(--dur-standard) var(--ease-gothic);
}
.dl-repeat-toggle .dl-rt-sub {
    font-family: var(--font-main);
    font-size: 12px; font-style: italic; letter-spacing: 0.2px; line-height: 1.3;
    color: var(--text-muted);
    text-transform: none; font-weight: 400;
}

/* lunar-phase switch (CSS-driven by .on) */
.dl-repeat-toggle .dl-rt-switch {
    position: relative; flex: 0 0 auto;
    width: 54px; height: 24px; border-radius: 12px;
    background: radial-gradient(100% 140% at 50% 0%, rgba(16, 7, 38, 0.92), rgba(4, 1, 12, 0.96));
    border: 1px solid var(--border-input);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.7);
    transition: border-color var(--dur-quick) var(--ease-gothic), box-shadow var(--dur-quick) var(--ease-gothic);
}
.dl-repeat-toggle .dl-rt-stars { position: absolute; inset: 0; opacity: 0.5; }
.dl-repeat-toggle .dl-rt-stars i { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: var(--text-muted); }
.dl-repeat-toggle .dl-rt-stars i:nth-child(1) { left: 11px; top: 7px; }
.dl-repeat-toggle .dl-rt-stars i:nth-child(2) { left: 18px; top: 15px; }
.dl-repeat-toggle .dl-rt-stars i:nth-child(3) { left: 25px; top: 6px; }
.dl-repeat-toggle .dl-rt-knob {
    position: absolute; top: 50%; left: 3px; width: 18px; height: 18px;
    transform: translateY(-50%);
    border-radius: 50%; overflow: hidden;
    background: radial-gradient(circle at 35% 30%, #6a4a98, #2a1850);
    border: 1px solid rgba(150, 100, 220, 0.4);
    transition: left var(--dur-quick) var(--ease-spring), box-shadow var(--dur-quick) var(--ease-gothic), background var(--dur-quick) var(--ease-gothic);
}
/* offset disc carves a crescent when OFF */
.dl-repeat-toggle .dl-rt-knob::after {
    content: ""; position: absolute; top: -2px; left: 5px; width: 18px; height: 22px;
    border-radius: 50%; background: var(--bg-input);
    transition: left var(--dur-quick) var(--ease-spring), opacity var(--dur-quick) var(--ease-gothic);
}

/* ON — lit, restrained: glyph & title brighten, orb slides to full moon */
.dl-repeat-toggle.on { border-color: var(--border-mid); background: linear-gradient(180deg, rgba(26, 9, 60, 0.55), rgba(12, 4, 34, 0.5)); }
.dl-repeat-toggle.on .dl-rt-glyph { color: var(--accent-hover); filter: drop-shadow(0 0 6px var(--accent-glow)); }
.dl-repeat-toggle.on .dl-rt-title { color: var(--accent-hover); }
.dl-repeat-toggle.on .dl-rt-switch { border-color: var(--border-bright); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6), 0 0 13px var(--accent-glow); }
.dl-repeat-toggle.on .dl-rt-knob {
    left: 33px;
    background: radial-gradient(circle at 38% 32%, #f3e3ff, #9a6ae0);
    box-shadow: 0 0 11px var(--accent-glow), inset 0 0 4px rgba(255, 255, 255, 0.5);
}
.dl-repeat-toggle.on .dl-rt-knob::after { left: 24px; opacity: 0; }

@media (prefers-reduced-motion: reduce) {
    .dl-repeat-toggle .dl-rt-knob,
    .dl-repeat-toggle .dl-rt-knob::after,
    .dl-repeat-toggle .dl-rt-glyph { transition: none; }
}

/* User-requested swap (deadline modal only): the day/month dropdown TRIGGER read
   white-at-rest / violet-on-hover; invert to violet-at-rest / white-on-hover. */
#deadline-modal .dl-month-trigger { color: var(--text-secondary); }
#deadline-modal .dl-month-trigger:hover { color: var(--text-primary); }

/* X-7: event-duration block — gothic «Свеча». Two candles flank centered inputs;
   the event «burns» for its duration (empty = instant, no live window). */
.dl-duration-row {
    position: relative;
    width: 100%;
    margin-top: 13px;
    padding: 13px 12px 11px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-mid);
    background: radial-gradient(110% 120% at 50% 0%, rgba(150, 80, 255, 0.06), transparent 60%),
                linear-gradient(180deg, rgba(23, 14, 42, 0.55), rgba(16, 10, 29, 0.55));
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4) inset, 0 0 24px -14px var(--accent-glow);
}
.dl-duration-row[hidden] { display: none; }

/* enriched frame: 4 minimalist ornate corners (arc + bead) */
.dl-dur-corner { position: absolute; width: 19px; height: 19px; color: var(--border-mid); opacity: 0.7; pointer-events: none; }
.dl-dur-corner.tl { top: 6px; left: 6px; }
.dl-dur-corner.tr { top: 6px; right: 6px; transform: scaleX(-1); }
.dl-dur-corner.bl { bottom: 6px; left: 6px; transform: scaleY(-1); }
.dl-dur-corner.br { bottom: 6px; right: 6px; transform: scale(-1, -1); }

/* legend notched into the top border */
.dl-dur-legend {
    position: absolute; top: -8px; left: 50%; transform: translateX(-50%); z-index: 2;
    display: inline-flex; align-items: center; gap: 8px;
    font-family: var(--font-label); font-size: 10px; letter-spacing: 2px; text-transform: uppercase;
    color: var(--text-secondary); background: var(--bg-modal); padding: 0 7px; white-space: nowrap;
}
.dl-dur-legend i { width: 4px; height: 4px; background: var(--text-muted); transform: rotate(45deg); flex: 0 0 auto; }

/* two candles | centered inputs | two candles */
.dl-dur-stage { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; justify-items: center; }

.dl-dur-candle { position: relative; width: 40px; height: 84px; display: grid; place-items: end center; }
.dl-dur-candle svg { width: 40px; height: 84px; overflow: visible; display: block; }
.dl-dur-candle.right svg { transform: scaleX(-1); }              /* mirror for symmetry */
.dl-dur-candle.right .dl-flame,
.dl-dur-candle.right .dl-halo { animation-delay: -1.5s; }        /* out-of-phase flicker */
.dl-flame { transform-origin: 30px 40px; animation: dlFlicker 3.2s var(--ease-gothic) infinite; }
.dl-halo  { transform-origin: 30px 34px; animation: dlHalo 3.2s var(--ease-gothic) infinite; }
@keyframes dlFlicker {
    0%, 100% { transform: translateY(0) scaleY(1) rotate(0); }
    30% { transform: translateY(-0.5px) scaleY(1.035) rotate(-0.7deg); }
    60% { transform: translateY(0.4px) scaleY(0.98) rotate(0.5deg); }
}
@keyframes dlHalo { 0%, 100% { opacity: 0.5; transform: scale(1); } 50% { opacity: 0.66; transform: scale(1.05); } }

/* inputs: strict grid — col1 hours, col2 dagger, col3 minutes; rows up/number/down/unit */
.dl-dur-fields {
    display: grid; grid-template-columns: 44px 24px 44px; grid-template-rows: auto auto auto auto;
    align-items: center; justify-items: center; row-gap: 2px;
}
.dl-dur-num {
    font-family: var(--font-title); font-weight: 600; font-size: 30px; line-height: 1; color: var(--text-primary);
    background: transparent; border: 0; width: 44px; height: 33px; text-align: center; outline: none; padding: 0;
    position: relative; top: 1.5px;  /* optical-center the cap-height numeral between the arches */
    text-shadow: 0 0 14px rgba(150, 80, 255, 0.28);
    -moz-appearance: textfield; appearance: textfield;
    transition: text-shadow var(--dur-quick) var(--ease-gothic);
}
.dl-dur-num::-webkit-outer-spin-button,
.dl-dur-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.dl-dur-num::placeholder { color: var(--text-muted); opacity: 0.5; }
.dl-dur-fields:focus-within .dl-dur-num:focus { text-shadow: 0 0 20px rgba(170, 100, 255, 0.55); }
.dl-dur-unit { font-family: var(--font-label); font-size: 10px; letter-spacing: 1.3px; color: var(--text-muted); text-transform: lowercase; }

/* arch steppers — gothic lancet + finial (light outline; up = +, down = −) */
.dl-dur-step {
    width: 44px; height: 14px; display: grid; place-items: center; color: var(--text-muted);
    background: transparent; border: 0; cursor: pointer; padding: 0;
    transition: color var(--dur-quick) var(--ease-gothic);
}
.dl-dur-step svg { width: 21px; height: 12px; display: block; transition: transform 0.16s var(--ease-spring), filter var(--dur-quick) var(--ease-gothic); }
.dl-dur-step.down svg { transform: rotate(180deg); }
.dl-dur-step:hover { color: var(--accent-hover); }
.dl-dur-step.up:hover svg { transform: translateY(-2px); filter: drop-shadow(0 0 5px var(--accent-glow)); }
.dl-dur-step.down:hover svg { transform: rotate(180deg) translateY(-2px); filter: drop-shadow(0 0 5px var(--accent-glow)); }
.dl-dur-step:active svg { transform: scale(0.85); }
.dl-dur-step.down:active svg { transform: rotate(180deg) scale(0.85); }

/* dagger separator — middle column, centered on the number axis */
.dl-dur-sep { display: flex; align-items: center; justify-content: center; color: var(--border-mid); align-self: center; justify-self: center; }
.dl-dur-sep svg { width: 11px; height: 47px; display: block; }

@media (prefers-reduced-motion: reduce) {
    .dl-flame, .dl-halo { animation: none !important; }
}

/* Optional time row inside date-mode deadline (Extension 7) */
.dl-date-time-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 8px;
}
.dl-date-time-label {
    display: flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-label);
    font-size: 10.5px;
    color: var(--text-secondary);
    letter-spacing: 0.5px;
    white-space: nowrap;
    flex-shrink: 0;
}
.dl-date-time-input {
    width: 110px;
    flex-shrink: 0;
    padding: 5px 8px !important;
    font-size: 12px !important;
}

/* Monthday validation warning — inline below stepper, shown only when value is clamped */
.dl-monthday-warn {
    color: rgba(255, 180, 80, 0.90);
    font-style: normal;
    font-weight: 600;
    border-left: 2px solid rgba(255, 160, 50, 0.55);
    padding-left: 7px;
    margin-top: 9px;
    line-height: 1.5;
    transition: opacity var(--transition);
}
.dl-monthday-warn[hidden] { display: none; }

/* Static short-month footnote — appears only when entered day ≥ 29 */
.dl-monthday-note {
    opacity: 0.65;
    font-style: italic;
    margin-top: 5px;
}
.dl-monthday-note[hidden] { display: none; }

/* ===== GOTHIC MONTH PICKER (custom dropdown replacing native <select>) =====
   Keeps native <select id="dl-month"> hidden for value storage; custom UI
   sits on top. Animated with ease-emerge for unhurried gothic materialisation. */
.dl-month-picker { position: relative; }

.dl-month-trigger {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    cursor: pointer;
    transition: border-color var(--transition), box-shadow var(--transition);
    text-align: left;
    letter-spacing: 0.3px;
}
.dl-month-trigger:hover { border-color: rgba(140, 60, 255, 0.5); color: var(--accent-hover); }
.dl-month-trigger:focus-visible {
    outline: none;
    border-color: rgba(150, 70, 255, 0.55);
    box-shadow: 0 0 0 2px rgba(110, 30, 210, 0.18);
}

.dl-month-chevron {
    width: 11px;
    height: 11px;
    flex-shrink: 0;
    opacity: 0.55;
    transition: transform var(--dur-quick) var(--ease-gothic), opacity var(--transition);
    /* Sword default: pointing up = dropdown closed (can expand) */
}
.dl-month-picker.open .dl-month-chevron {
    /* Sword rotated 180° = pointing down = dropdown open (can collapse).
       Matches the site-wide convention: btn-note-toggle.open / btn-subtask-toggle.open */
    transform: rotate(180deg);
    opacity: 0.85;
}
.dl-month-picker.open .dl-month-trigger {
    border-color: rgba(140, 60, 255, 0.45);
}

.dl-month-list {
    position: absolute;
    top: calc(100% + 5px);
    left: 0;
    right: 0;
    background: #06021a;
    border: 1px solid rgba(140, 60, 255, 0.32);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md), 0 0 20px rgba(80, 20, 180, 0.14);
    z-index: 310;  /* I-17: was 200 = same as modal-overlay; raised so dropdowns clear any stacked modal */
    max-height: 224px;
    overflow-y: auto;
    padding: 5px 0;

    /* Scroll-bar: thin gothic purple */
    scrollbar-width: thin;
    scrollbar-color: rgba(120, 50, 220, 0.4) transparent;

    /* Veil-lift animation */
    opacity: 0;
    transform: translateY(-7px) scaleY(0.96);
    transform-origin: top center;
    pointer-events: none;
    transition:
        opacity var(--dur-quick) var(--ease-emerge),
        transform var(--dur-quick) var(--ease-emerge);
}
.dl-month-list::-webkit-scrollbar { width: 4px; }
.dl-month-list::-webkit-scrollbar-thumb { background: rgba(120, 50, 220, 0.4); border-radius: 2px; }
.dl-month-list::-webkit-scrollbar-track { background: transparent; }

.dl-month-picker.open .dl-month-list {
    opacity: 1;
    transform: translateY(0) scaleY(1);
    pointer-events: auto;
}

/* S1-7: open-upward variant — when the trigger sits near the viewport bottom
   (mirrors .dl-weekday-picker.open-up so the month list never spills offscreen). */
.dl-month-picker.open-up .dl-month-list {
    top: auto;
    bottom: calc(100% + 5px);
    transform-origin: bottom center;
    transform: translateY(7px) scaleY(0.96);
}
.dl-month-picker.open.open-up .dl-month-list {
    transform: translateY(0) scaleY(1);
}

.dl-month-option {
    padding: 10px 14px;
    font-family: var(--font-main);
    font-size: 15px;
    color: var(--text-secondary);
    cursor: pointer;
    letter-spacing: 0.2px;
    transition: background var(--dur-micro), color var(--dur-micro);
    user-select: none;
}
.dl-month-option:hover {
    background: rgba(100, 25, 200, 0.18);
    color: var(--text-primary);
}
.dl-month-option.active {
    background: rgba(100, 25, 200, 0.28);
    color: var(--accent-hover);
    font-weight: 600;
}
/* ======================================================= */

/* ===== GOTHIC WEEKDAY PICKER (weektime mode)
   Reuses all .dl-month-picker/.dl-month-trigger/.dl-month-option styles.
   Only overrides needed: flex growth inside .weektime-row, and list height. */

/* Grow to fill weektime-row flex slot (same as .modal-input did for native select) */
.dl-weekday-picker {
    flex: 1;
    min-width: 0; /* prevent flex overflow */
}

/* Weekday list: show all 7 options without scrolling */
.dl-weekday-list {
    position: absolute;
    top: calc(100% + 5px);
    left: 0;
    right: 0;
    background: #06021a;
    border: 1px solid rgba(140, 60, 255, 0.32);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md), 0 0 20px rgba(80, 20, 180, 0.14);
    z-index: 310;  /* I-17: raised from 200 to match dl-month-list */
    max-height: 270px; /* 7 × ~38px — no scroll needed */
    overflow-y: auto;
    padding: 5px 0;
    scrollbar-width: thin;
    scrollbar-color: rgba(120, 50, 220, 0.4) transparent;

    /* Veil-lift animation — identical to month list */
    opacity: 0;
    transform: translateY(-7px) scaleY(0.96);
    transform-origin: top center;
    pointer-events: none;
    transition:
        opacity var(--dur-quick) var(--ease-emerge),
        transform var(--dur-quick) var(--ease-emerge);
}

/* Open-upward variant: when picker is near viewport bottom */
.dl-weekday-picker.open-up .dl-weekday-list {
    top: auto;
    bottom: calc(100% + 5px);
    transform-origin: bottom center;
}
.dl-weekday-picker.open-up .dl-weekday-list {
    transform: translateY(7px) scaleY(0.96);
}
.dl-weekday-picker.open.open-up .dl-weekday-list {
    transform: translateY(0) scaleY(1);
}
.dl-weekday-list::-webkit-scrollbar { width: 4px; }
.dl-weekday-list::-webkit-scrollbar-thumb { background: rgba(120, 50, 220, 0.4); border-radius: 2px; }
.dl-weekday-list::-webkit-scrollbar-track { background: transparent; }

.dl-weekday-picker.open .dl-weekday-list {
    opacity: 1;
    transform: translateY(0) scaleY(1);
    pointer-events: auto;
}
.dl-weekday-picker.open .dl-month-chevron {
    transform: rotate(180deg);
    opacity: 0.85;
}
.dl-weekday-picker.open .dl-month-trigger {
    border-color: rgba(140, 60, 255, 0.45);
}

/* Repeat-modal weekday picker — mirror the trigger ink: violet by default,
   white on hover (matches the .grp-picker convention; opposite of the deadline
   pickers' white-default). Scoped to the repeat anchor picker only. */
#repeat-wd-picker .dl-month-trigger { color: var(--accent-hover); }
#repeat-wd-picker .dl-month-trigger .dl-month-chevron { opacity: 0.8; }
#repeat-wd-picker .dl-month-trigger:hover { color: var(--text-primary); }
#repeat-wd-picker .dl-month-trigger:hover .dl-month-chevron { opacity: 1; }

/* ======================================================= */

/* ===== CUSTOM NUMBER STEPPER (monthday) ===== */
.number-stepper-wrap {
    display: flex;
    align-items: center;
    gap: 0;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    overflow: hidden;
    transition: border-color var(--transition);
}
.number-stepper-wrap:focus-within { border-color: rgba(150, 70, 255, 0.55); }

/* Remove native browser spinners */
.stepper-input::-webkit-outer-spin-button,
.stepper-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper-input { -moz-appearance: textfield; }

.stepper-input {
    flex: 1;
    border: none !important;
    border-radius: 0 !important;
    border-left: 1px solid var(--border-input) !important;
    border-right: 1px solid var(--border-input) !important;
    text-align: center;
    background: transparent;
    font-size: 15px;
    padding: 9px 8px;
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-weight: 500;
    outline: none;
}
.stepper-input:focus { border-color: transparent !important; }

.stepper-btn {
    width: 44px;
    height: 100%;
    min-height: 40px;
    border: none;
    background: rgba(100, 30, 200, 0.12);
    color: var(--text-secondary);
    font-family: var(--font-mono);
    font-size: 18px;
    font-weight: 400;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition);
    flex-shrink: 0;
    line-height: 1;
    padding-bottom: 2px;
}
.stepper-btn:hover { background: var(--accent-soft); color: var(--accent-hover); }
.stepper-btn:active { background: rgba(120, 40, 240, 0.25); transform: scale(0.92); }

/* Priority modal */
.modal-prio-selector {
    flex-direction: column;
    gap: 6px;
    margin-bottom: 16px;
}
.modal-prio-selector .prio-btn {
    padding: 10px 14px;
    border-radius: var(--radius-sm);
    justify-content: flex-start;
    font-size: 12px;
}

/* ── Repeat modal grid ── */
.repeat-modal-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 5px;
    margin-bottom: 16px;
}
.repeat-modal-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 12px 8px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg-input);
    color: var(--text-muted);
    font-family: var(--font-label);
    font-size: 10.5px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition);
    letter-spacing: 1.5px;
    text-transform: uppercase;
}
.repeat-modal-btn svg { width: 18px; height: 18px; flex-shrink: 0; }
.repeat-modal-btn:hover { border-color: var(--border-mid); color: var(--text-secondary); background: rgba(60,15,130,0.18); }
.repeat-modal-btn.active {
    background: var(--accent-soft);
    color: var(--accent-hover);
    border-color: rgba(140, 60, 255, 0.45);
    box-shadow: 0 0 10px rgba(130, 50, 230, 0.15);
}
/* "Нет" (off) spans the full row as a distinct off-switch bar above the 2×2
   cadence grid — icon and label sit side by side instead of stacked. */
.repeat-modal-btn[data-repeat="none"] {
    grid-column: 1 / -1;
    flex-direction: row;
    gap: 9px;
    padding: 10px 8px;
}

/* ── Repeat anchor section ── */
.repeat-anchor-section {
    margin-bottom: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
}
.repeat-anchor-header {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 10px;
}
.repeat-anchor-title {
    font-family: var(--font-label);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--text-muted);
}
.repeat-anchor-opt {
    font-family: var(--font-label);
    font-size: 9.5px;
    color: rgba(160, 130, 210, 0.45);
    font-style: italic;
    letter-spacing: 0.5px;
}
.repeat-anchor-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 8px;
}
.repeat-anchor-row:last-of-type { margin-bottom: 0; }
/* Weekday picker in anchor reuses dl-weekday-picker, needs flex:1 */
.repeat-anchor-row .dl-weekday-picker { flex: 1; }
/* Time input in anchor: stays as flex row, seg-input-row takes all space */
.repeat-anchor-time-row {
    /* keep display:flex from .repeat-anchor-row — seg-input-row fills it via flex:1 */
    width: 100%;
}
.repeat-anchor-time-row .seg-input-row {
    flex: 1;
    min-width: 0;
    width: 100%;
}
/* Problem 2: the time field itself fills the WHOLE row width — the clear & clock
   icons become trailing affordances overlaid inside its right edge instead of
   sitting beside it as separate boxes that left an empty gap. */
.repeat-anchor-time-row .seg-input-row .seg-input {
    width: 100%;
    flex: 1;
    padding-right: 78px; /* reserve room for the two overlaid icon buttons */
}
.repeat-anchor-time-row .seg-clear-btn,
.repeat-anchor-time-row .seg-picker-btn {
    position: absolute;
    top: 4px;
    bottom: 4px;
    height: auto;
    background: transparent;
    border-color: transparent;
}
.repeat-anchor-time-row .seg-picker-btn { right: 6px; }
.repeat-anchor-time-row .seg-clear-btn  { right: 42px; }
.repeat-anchor-time-row .seg-clear-btn:hover,
.repeat-anchor-time-row .seg-picker-btn:hover { background: var(--accent-soft); border-color: var(--border-mid); }
.repeat-anchor-time-row .modal-input:not(.seg-input) { display: none; }
/* Monthday label — same opacity as dl-hint notes */
.repeat-anchor-monthday-label {
    font-size: 10.5px !important;
    opacity: 0.75;
    margin-top: -2px;
}
.repeat-anchor-monthday-note-below {
    opacity: 0.75;
    margin-top: -2px;
    margin-bottom: 2px;
}
/* Stepper wrap fills full row width */
.repeat-stepper-wrap {
    width: 100%;
    justify-content: center;
}

/* ── Group section drag handle ───────────────────────────────── */
.group-drag-handle {
    width: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    cursor: grab;
    color: var(--text-muted);
    flex-shrink: 0;
    transition: width 0.18s ease, opacity 0.18s ease;
    pointer-events: none;
}
.group-header:hover .group-drag-handle {
    width: 18px;
    opacity: 0.55;
    pointer-events: auto;
}
.group-drag-handle:hover { opacity: 0.9 !important; }
.group-drag-handle svg { width: 14px; height: 14px; flex-shrink: 0; }

/* ── Drag handle: left column, below the coffin checkbox ─────────────────
   The handle sits in a narrow left column (same width as the coffin checkbox).
   It's absolute, centred horizontally within that column, and pushed to the
   lower half of the item so it reads as "below the coffin, not beside it".
   Bigger dots (r=1.8), more visible — clearly an affordance, not a button.   */
.task-item { position: relative; }

.task-check-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    flex-shrink: 0;
}
.drag-handle {
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--border-mid);
    opacity: 0;
    transition: opacity 0.22s ease, color 0.15s ease;
    pointer-events: none;
    flex-shrink: 0;
}
.drag-handle svg {
    width: 20px;
    height: 20px;
    pointer-events: none;
    display: block;
}
/* Show on hover of the whole item — kept clearly visible, not a faint ghost. */
.task-item:hover .drag-handle { opacity: 0.62; color: var(--text-muted); }
/* Completed (or cycle-completed) tasks can't be dragged — never show the handle. */
.task-item.checked .drag-handle,
.task-item.cycle-checked .drag-handle { display: none; }
/* Brighter when actively dragging */
.sortable-chosen .drag-handle,
.sortable-drag    .drag-handle {
    opacity: 0.85;
    color: var(--accent);
}
@keyframes handlePop {
    0%   { transform: scale(1);    }
    40%  { transform: scale(1.3);  }
    100% { transform: scale(1);    }
}
.sortable-chosen .drag-handle svg {
    animation: handlePop 0.20s var(--ease-spring);
}
@media (prefers-reduced-motion: reduce) {
    .sortable-chosen .drag-handle svg { animation: none; }
}
@media (max-width: 520px) {
    .task-item .drag-handle { opacity: 0.3; }
    .task-item:hover .drag-handle { opacity: 0.62; }
}

/* ── Drag handle: large items — positioning via inline styles from positionDragHandles().
   The JS writes handle.style.position/top/left directly on each item, so no class-based
   CSS rules are needed here. Only the default flex-flow state lives in .task-check-col. */

/* ── Two-step destructive confirm ─────────────────────────────────────────
   First click arms the button: it glows danger-red as a visual warning.
   Second click within 3 s fires the action.  Auto-disarms after 3 s.       */
.btn-tool.confirm-armed,
.btn-group-action.confirm-armed {
    background: var(--prio-high-bg) !important;
    color: var(--prio-high) !important;
    border-color: var(--prio-high-border) !important;
    animation: armedPulse 0.8s ease-in-out infinite;
}
@keyframes armedPulse {
    0%, 100% { box-shadow: 0 0 0 0   rgba(220, 30, 70, 0); }
    50%       { box-shadow: 0 0 0 3px rgba(220, 30, 70, 0.30); }
}
@media (prefers-reduced-motion: reduce) {
    .btn-tool.confirm-armed,
    .btn-group-action.confirm-armed { animation: none; }
}

/* ── Split-group zone headers ─────────────────────────────────────────────
   Both headers share identical type/color — one visual system.
   "Done" header is clickable and has a collapse chevron.                     */
.split-zone-header {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 6px 8px 5px;
    margin: 8px 0 4px;
    font-family: var(--font-label);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    color: var(--text-secondary);          /* was --text-primary (near-white); now violet */
    border-bottom: 1px solid rgba(100, 35, 170, 0.30);
    user-select: none;
}
/* P8: zone icon (first SVG in header) at full opacity — matches text brightness.
   Only the .split-chevron gets its own reduced opacity below. */
.split-zone-header svg { width: 12px; height: 12px; flex-shrink: 0; opacity: 1; }
/* Chevron is a navigation affordance — keep it slightly quieter than the label */
.split-done-header .split-chevron { opacity: 0.55; }
/* ROOT CAUSE FIX (task 2): transition was set but NO end-state rule existed.
   Convention matches btn-note-toggle / btn-subtask-toggle throughout the site:
   sword at 0° = content collapsed (pointing up = "expand me");
   sword at 180° = content visible (pointing down = "collapse me"). */
.split-done-header .split-chevron          { transform: rotate(180deg); }  /* default: content visible */
.split-done-header.collapsed .split-chevron { transform: rotate(0deg);   }  /* collapsed: content hidden */

.split-active-header {
    /* Now collapsible — mirrors split-done-header */
    cursor: pointer;
    transition: color var(--transition), background var(--transition);
    border-radius: var(--radius-xs);
}
.split-active-header:hover {
    color: rgba(200, 145, 255, 0.92);
    background: rgba(110, 30, 200, 0.10);
}
.split-active-header .split-chevron {
    margin-left: auto;
    transition: transform var(--transition);
    flex-shrink: 0;
}
.split-active-header.collapsed .split-chevron { transform: rotate(180deg); }

/* Active-wrap collapse — same grid-row trick as done-wrap */
.split-active-wrap {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic),
                opacity             var(--dur-collapse) var(--ease-gothic);
    opacity: 1;
}
.split-active-wrap.collapsed {
    grid-template-rows: 0fr;
    opacity: 0;
}
.split-active-wrap > ul {
    overflow: hidden;
    min-height: 0;
}

.split-done-header {
    cursor: pointer;
    transition: color var(--transition), background var(--transition);
    border-radius: var(--radius-xs);
}
/* Gothic-compatible hover: soft violet glow, not bright white */
.split-done-header:hover {
    color: rgba(200, 145, 255, 0.92);
    background: rgba(110, 30, 200, 0.10);
}
.split-done-header .split-chevron {
    margin-left: auto;
    transition: transform var(--transition);
    flex-shrink: 0;
}
/* ── Split done-zone collapse animation ──────────────────────────────────────
   Grid-row trick: animates from 0fr (collapsed) to 1fr (expanded) without
   knowing the content height. The inner ul needs min-height:0 to allow
   shrinking below its natural size. Reduced-motion fallback is instant toggle. */
.split-done-wrap {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic),
                opacity             var(--dur-collapse) var(--ease-gothic);
    opacity: 1;
}
.split-done-wrap.collapsed {
    grid-template-rows: 0fr;
    opacity: 0;
}
.split-done-wrap > ul {
    overflow: hidden;
    min-height: 0;
}

@media (prefers-reduced-motion: reduce) {
    .split-done-wrap { transition: none; }
}

/* ── Pinned zone (split mode) — "Закреплённые" header + collapsible body ──── */
.split-pinned-header {
    cursor: pointer;
    transition: color var(--transition), background var(--transition);
    border-radius: var(--radius-xs);
    color: var(--accent-hover);
    border-bottom-color: rgba(150, 80, 240, 0.35);
}
.split-pinned-header:hover {
    color: rgba(210, 160, 255, 0.95);
    background: rgba(110, 30, 200, 0.10);
}
/* Match the crisp pin glyph of the form "Закрепить задачу" button — no glow. */
.split-pinned-header > svg:not(.split-chevron) {
    width: 13px;
    height: 13px;
}
.split-pinned-header .split-chevron {
    margin-left: auto;
    transition: transform var(--transition);
    flex-shrink: 0;
}
.split-pinned-header.collapsed .split-chevron { transform: rotate(180deg); }
.split-pinned-wrap {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic),
                opacity             var(--dur-collapse) var(--ease-gothic);
    opacity: 1;
}
.split-pinned-wrap.collapsed { grid-template-rows: 0fr; opacity: 0; }
.split-pinned-wrap > ul {
    overflow: hidden;
    min-height: 0;
    list-style: none;
    padding: 0;
    margin: 0;
}
@media (prefers-reduced-motion: reduce) {
    .split-pinned-wrap { transition: none; }
}

/* ── drag-over portal glow clears on dragend — see onDragEnd ── */
.task-item.kb-focused {
    outline: 2px solid rgba(180, 100, 255, 0.60);
    outline-offset: -1px;
    background: var(--bg-item-hover);
    border-color: rgba(150, 70, 255, 0.45);
}
.task-item.kb-focused .task-actions { opacity: 1; }

.btn-sound {
    position: fixed;
    bottom: 22px;
    right: 22px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--bg-app);
    border: 1px solid var(--border-mid);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: all var(--transition);
    z-index: 50;
    padding: 0;
    backdrop-filter: blur(10px);
}
.btn-sound:hover { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.55); box-shadow: var(--shadow-glow); }
.btn-sound svg { width: 15px; height: 15px; }
.btn-sound.on .icon-sound-off { display: none; }
.btn-sound.off .icon-sound-on { display: none; }
.btn-sound.on { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.55); }

/* ── Shortcuts toggle button (UX-3) ──────────────────────────────────────── */
.btn-shortcuts-toggle {
    position: fixed;
    bottom: 68px; /* stacked above btn-sound (22px bottom + 40px height + 6px gap) */
    right: 22px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--bg-app);
    border: 1px solid var(--border-mid);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: all var(--transition);
    z-index: 50;
    padding: 0;
    backdrop-filter: blur(10px);
    font-family: var(--font-label);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0;
    line-height: 1;
}
.btn-shortcuts-toggle:hover {
    color: var(--accent-hover);
    border-color: rgba(140, 60, 255, 0.55);
    box-shadow: var(--shadow-glow);
}
.btn-shortcuts-toggle.active {
    color: var(--accent-hover);
    border-color: rgba(140, 60, 255, 0.55);
    background: rgba(100, 35, 200, 0.15);
}

/* ── п.17 Звук пера toggle — stacked above the shortcuts button ──────────────── */
.btn-pen-sound {
    position: fixed;
    bottom: 114px; /* 22 + 2×(40+6) */
    right: 22px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--bg-app);
    border: 1px solid var(--border-mid);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: all var(--transition);
    z-index: 50;
    padding: 0;
    backdrop-filter: blur(10px);
}
.btn-pen-sound:hover { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.55); box-shadow: var(--shadow-glow); }
.btn-pen-sound svg { width: 23px; height: 23px; overflow: visible; }
.btn-pen-sound.on { color: var(--accent-hover); border-color: rgba(140, 60, 255, 0.55); }

/* ── Volume bar «Сосуд»: the button BODY itself morphs upward into a vessel.
   Revealed only when sound is ON; drag the channel to set master volume. ───── */
.btn-pen-sound {
    /* 20px radius (= half of the 40px circle, so identical at rest) keeps STRAIGHT
       sides when the body grows tall → a stadium capsule, not a bulging ellipse. */
    border-radius: 20px;
    transition: height var(--dur-ritual, 520ms) var(--ease-gothic, cubic-bezier(.16,1,.3,1)),
                border-color var(--transition), box-shadow var(--transition), color var(--transition);
    overflow: visible;          /* keep the OFF quill-lift visible (it draws outside) */
}
.btn-pen-sound.on:hover, .btn-pen-sound.on.pen-live { height: 152px; border-color: var(--border-bright); }
.btn-pen-sound .pen-ico-slot, .btn-pen-sound .pen-pct {
    position: absolute; left: 0; right: 0; bottom: 0; height: 40px;
    display: flex; align-items: center; justify-content: center; pointer-events: none;
}
/* base counter: while dragging, the quill crossfades to the volume % (B) */
.btn-pen-sound .pen-ico-slot { transition: opacity 0.2s var(--ease-gothic, cubic-bezier(.16,1,.3,1)); }
.btn-pen-sound .pen-pct {
    /* centre in the base gap between the channel bottom (42px) and the container
       bottom (0) → 42px slot centres the digits at 21px, matching the icon. */
    height: 42px;
    opacity: 0; color: #ecd9ff;
    font-family: var(--font-label); font-size: 14px; font-weight: 700; letter-spacing: 1px;
    /* lining-nums = uniform-height digits (Cormorant defaults to old-style figures) */
    font-variant-numeric: lining-nums tabular-nums;
    text-shadow: 0 0 9px var(--accent-glow), 0 0 2px rgba(200, 150, 255, 0.55);
    transition: opacity 0.2s var(--ease-gothic, cubic-bezier(.16,1,.3,1));
}
.btn-pen-sound.pen-live .pen-ico-slot { opacity: 0; }
.btn-pen-sound.pen-live .pen-pct { opacity: 1; }
.btn-pen-sound .pen-chan {
    position: absolute; left: 50%; top: 14px; bottom: 42px; width: 12px;
    transform: translateX(-50%); border-radius: 6px;
    background: rgba(4, 1, 14, 0.5);
    box-shadow: inset 0 0 0 1px rgba(150, 90, 255, 0.5), inset 0 1px 4px rgba(0, 0, 0, 0.5);
    overflow: hidden; opacity: 0; pointer-events: none; cursor: grab;
    transition: opacity 0.3s 0.08s var(--ease-gothic, cubic-bezier(.16,1,.3,1));
}
.btn-pen-sound.on:hover .pen-chan, .btn-pen-sound.on.pen-live .pen-chan { opacity: 1; pointer-events: auto; }
.btn-pen-sound.pen-live .pen-chan { cursor: grabbing; }
.btn-pen-sound .pen-fill {
    position: absolute; left: 0; right: 0; bottom: 0; height: var(--pv, 100%); border-radius: 6px;
    background: linear-gradient(180deg, var(--accent-hover), var(--accent) 60%, #5e22b8);
    transition: height 0.12s linear;
}
/* meniscus — a clean bright white dot on the liquid surface (no dark rim / halo) */
.btn-pen-sound .pen-fill::before {
    content: ''; position: absolute; top: -1px; left: 50%; transform: translateX(-50%);
    width: 7px; height: 3px; border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.35) 60%, transparent);
}

/* the quill group lifts off the page when sound is OFF (no strikethrough) */
.btn-pen-sound .pen-q {
    transition: transform var(--dur-ritual, 520ms) var(--ease-gothic, cubic-bezier(.16,1,.3,1));
    transform-box: view-box;
    transform-origin: 380px 160px;
}
.btn-pen-sound.off .pen-q { transform: translate(28px, -100px) rotate(-7deg); }
@media (prefers-reduced-motion: reduce) {
    .btn-pen-sound, .btn-pen-sound .pen-q, .btn-pen-sound .pen-chan, .btn-pen-sound .pen-fill { transition: none; }
}

/* ===== SHORTCUTS HINT ===== */
.shortcuts-hint {
    position: fixed;
    bottom: 22px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--bg-modal);
    border: 1px solid var(--border-mid);
    border-radius: 99px;
    padding: 7px 20px;
    font-size: 10.5px;
    color: var(--text-secondary);
    box-shadow: var(--shadow-sm);
    z-index: 50;
    white-space: nowrap;
    font-family: var(--font-label);
    backdrop-filter: blur(10px);
    letter-spacing: 1px;
    /* UX-3: animated appearance */
    animation: shortcutsIn 0.18s var(--ease-gothic) both;
}
@keyframes shortcutsIn {
    from { opacity: 0; transform: translateX(-50%) translateY(6px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
kbd {
    display: inline-block;
    padding: 1px 6px;
    background: var(--bg-input);
    border: 1px solid var(--border-mid);
    border-radius: 3px;
    font-family: var(--font-mono);
    font-size: 9px;
}

/* ===== SCROLLBAR ===== */
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-mid); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-bright); }

/* ===== RESPONSIVE ===== */
/* Graceful container padding reduction as viewport narrows toward 780px container */
@media (max-width: 820px) {
    .todo-app { padding: 28px 22px 32px; }
}

/* R-1: 600-820px gap — iPad mini / landscape phones. Toolbar has 8+ buttons and
   can overflow horizontally without this breakpoint. */
@media (max-width: 640px) {
    .toolbar { gap: 8px; }
    /* On narrow screens centre the wrapped clusters so a half-empty last row
       doesn't get stretched apart by space-between. */
    .toolbar-actions { justify-content: center; gap: 8px 0; }
    .toolbar-group { padding: 0 9px; }
    .btn-tool { width: 30px; height: 30px; }
    .btn-tool svg { width: 13px; height: 13px; }
    .search-wrap { min-width: 0; }
}

@media (max-width:520px) {
    .todo-app { padding: 20px 14px 26px; margin-top: 10px; border-radius: var(--radius-lg); }
    .brand-name { font-size: 24px; letter-spacing: 10px; }
    .brand-svg { width: 24px; height: 29px; }
    .extra-row { flex-direction: column; }
    .prio-grid { grid-template-columns: 1fr 1fr; }
    .prio-grid-btn { font-size: 9.5px; padding: 5px 8px; }
    .priority-selector { gap: 3px; }
    .prio-btn { font-size: 10px; padding: 5px 8px; }
    .subtask-list { grid-template-columns: 1fr; }
    .sub-split-inner { grid-template-columns: 1fr; }
    #form-sub-list { grid-template-columns: 1fr; }
    .shortcuts-hint { display: none !important; }
    .modal { width: calc(100vw - 24px); padding: 18px 16px; }
    .modal-deadline { width: calc(100vw - 24px); }
    .modal-note { width: calc(100vw - 24px); }
    .dl-mode-grid { grid-template-columns: repeat(2, 1fr); }
    .modal-actions { gap: 4px; }
    .btn-modal-cancel, .btn-modal-danger, .btn-modal-confirm { padding: 6px 11px; font-size: 10px; }
    .toolbar { flex-wrap: wrap; }
    .task-actions { gap: 1px; }
    .btn-task-action { width: 25px; height: 25px; }
    .btn-task-action svg { width: 11px; height: 11px; }
    .weektime-row { flex-direction: column; }
    .drag-handle { opacity: 0.5; }
    .number-stepper-wrap { width: 100%; }
    .dl-side-panel { min-width: 44px; max-width: 44px; }
    .dl-side-countdown { font-size: 8.5px; }
    .dl-side-date { font-size: 7.5px; }
    /* D-2: tag-cloud becomes a single horizontally-scrollable row on mobile.
       flex-wrap:nowrap + overflow-x:auto means chips never push content below the toolbar. */
    .tag-cloud {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        padding-bottom: 4px;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        -webkit-mask-image: linear-gradient(to right, black 85%, transparent 100%);
        mask-image: linear-gradient(to right, black 85%, transparent 100%);
    }
    .tag-cloud::-webkit-scrollbar { display: none; }
    .tag-chip { flex-shrink: 0; }
}

@media (max-width:360px) {
    .todo-app { padding: 14px 10px 20px; }
    .brand-name { font-size: 20px; letter-spacing: 7px; }
    .brand-emblem { display: none; }
    .dl-mode-grid { grid-template-columns: repeat(2, 1fr); }
}

/* 6g: touch devices have no reliable hover — reveal row/subtask actions instead
   of depending on the tap-to-emulate-hover quirk, and enlarge tap targets to a
   comfortable size. Scoped to coarse pointers so desktop/mouse is untouched. */
@media (hover: none) and (pointer: coarse) {
    .task-actions,
    .sub-actions,
    .btn-sub-notes-always { opacity: 1; }
    /* P-E: no hover on touch — keep the deadline pill open so the countdown is visible */
    .sub-deadline-wrapper { grid-template-rows: 1fr; }
    .sub-deadline-inner   { opacity: 1; }
    .btn-task-action  { width: 30px; height: 30px; }
    .btn-task-action svg { width: 14px; height: 14px; }
    .btn-sub-action   { width: 26px; height: 26px; }
    .btn-group-action { width: 30px; height: 30px; }
    .drag-handle { opacity: 0.3; }
}

/* ===================================================
   NATIVE DATE / TIME INPUT — DARK GOTHIC THEME
   Strategy: color-scheme:dark forces the browser popup
   into dark OS mode (dark calendar/clock overlay).
   ::-webkit-datetime-edit-* styles the editable text
   fields to match the purple-black gothic palette.
   ::-webkit-calendar-picker-indicator gets gothic SVG icons.
   =================================================== */

/* Force browser popup into dark mode for both date and time inputs */
.modal-input[type="date"],
.modal-input[type="time"] {
    color-scheme: dark;
    /* Override padding to account for indicator space */
    padding-right: 8px;
}

/* Editable text region (the "yyyy-mm-dd" / "hh:mm" area) */
.modal-input[type="date"]::-webkit-datetime-edit,
.modal-input[type="time"]::-webkit-datetime-edit {
    color: var(--text-primary);
    padding: 0;
}

/* Each individual field segment (day, month, year, hour, minute) */
.modal-input[type="date"]::-webkit-datetime-edit-fields-wrapper,
.modal-input[type="time"]::-webkit-datetime-edit-fields-wrapper {
    padding: 0;
}

.modal-input[type="date"]::-webkit-datetime-edit-text,
.modal-input[type="time"]::-webkit-datetime-edit-text {
    color: var(--text-muted);
    padding: 0 1px;
}

.modal-input[type="date"]::-webkit-datetime-edit-day-field,
.modal-input[type="date"]::-webkit-datetime-edit-month-field,
.modal-input[type="date"]::-webkit-datetime-edit-year-field,
.modal-input[type="time"]::-webkit-datetime-edit-hour-field,
.modal-input[type="time"]::-webkit-datetime-edit-minute-field,
.modal-input[type="time"]::-webkit-datetime-edit-ampm-field {
    color: var(--text-primary);
    background: transparent;
    border-radius: 2px;
    padding: 0 1px;
}

/* Focused/selected field segment */
.modal-input[type="date"]::-webkit-datetime-edit-day-field:focus,
.modal-input[type="date"]::-webkit-datetime-edit-month-field:focus,
.modal-input[type="date"]::-webkit-datetime-edit-year-field:focus,
.modal-input[type="time"]::-webkit-datetime-edit-hour-field:focus,
.modal-input[type="time"]::-webkit-datetime-edit-minute-field:focus,
.modal-input[type="time"]::-webkit-datetime-edit-ampm-field:focus {
    background: rgba(110, 30, 210, 0.35);
    color: var(--accent-hover);
    outline: none;
}

/* Gothic lancet-window calendar icon:
   pointed arch (cathedral window) = gothic; grid lines inside = calendar.
   Highlighted apex dot = selected day. Readable at 16px. */
.modal-input[type="date"]::-webkit-calendar-picker-indicator {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 20' fill='none' stroke='%23c898ff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 20V9.5C2 4.5 5 2 9 2C13 2 16 4.5 16 9.5V20Z'/%3E%3Cline x1='2' y1='12.5' x2='16' y2='12.5' stroke-width='1.2'/%3E%3Cline x1='7.3' y1='12.5' x2='7.3' y2='20' stroke-width='1' opacity='0.55'/%3E%3Cline x1='10.7' y1='12.5' x2='10.7' y2='20' stroke-width='1' opacity='0.55'/%3E%3Cline x1='2' y1='16.2' x2='16' y2='16.2' stroke-width='1' opacity='0.55'/%3E%3Ccircle cx='9' cy='7.5' r='1.7' fill='%23c898ff' stroke='none' opacity='0.9'/%3E%3C/svg%3E");
    background-size: 16px 18px;
    background-repeat: no-repeat;
    background-position: center;
    background-color: transparent;
    width: 20px;
    height: 20px;
    cursor: pointer;
    opacity: 0.80;
    transition: opacity 0.18s;
}
.modal-input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* Gothic hourglass time icon:
   hourglass = universally "time"; converging lines + ornamental cap pins = gothic.
   Clean X-shaped silhouette reads clearly at 14px. */
.modal-input[type="time"]::-webkit-calendar-picker-indicator {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 20' fill='none' stroke='%23c898ff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='1.5' y1='2.5' x2='12.5' y2='2.5' stroke-width='2'/%3E%3Cline x1='1.5' y1='17.5' x2='12.5' y2='17.5' stroke-width='2'/%3E%3Cpath d='M2 2.5 L7 10.5 L2 17.5'/%3E%3Cpath d='M12 2.5 L7 10.5 L12 17.5'/%3E%3Ccircle cx='7' cy='10.5' r='1.3' fill='%23c898ff' stroke='none' opacity='0.85'/%3E%3Cline x1='1.5' y1='1' x2='1.5' y2='2.5' stroke-width='1.2' opacity='0.5'/%3E%3Cline x1='12.5' y1='1' x2='12.5' y2='2.5' stroke-width='1.2' opacity='0.5'/%3E%3Cline x1='1.5' y1='17.5' x2='1.5' y2='19' stroke-width='1.2' opacity='0.5'/%3E%3Cline x1='12.5' y1='17.5' x2='12.5' y2='19' stroke-width='1.2' opacity='0.5'/%3E%3C/svg%3E");
    background-size: 13px 18px;
    background-repeat: no-repeat;
    background-position: center;
    background-color: transparent;
    width: 20px;
    height: 20px;
    cursor: pointer;
    opacity: 0.80;
    transition: opacity 0.18s;
}
.modal-input[type="time"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* Size SVGs inside gothic lance stepper buttons */
.stepper-btn svg {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    display: block;
}

/* ===================================================
   SEGMENTED DATE/TIME INPUT  (Fix 3 + Fix 4)
   Replaces native date/time inputs with a styled
   custom widget that gives precise backspace-per-
   segment control and highlighted active segment.
   Gothic palette: dark bg, purple-violet accent.
   =================================================== */
.seg-input {
    display: flex;
    align-items: center;
    gap: 0;
    width: 100%;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    outline: none;
    transition: border-color var(--transition);
    cursor: text;
    box-sizing: border-box;
    user-select: none;
    -webkit-user-select: none;
}
.seg-input:focus {
    border-color: rgba(150, 70, 255, 0.55);
}
.seg-input:focus-within {
    border-color: rgba(150, 70, 255, 0.55);
}

/* Separator characters (: or .) between segments */
.seg-sep {
    color: var(--text-muted);
    padding: 0 2px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

/* Individual editable segment */
.seg {
    display: inline-block;
    color: var(--text-secondary);
    border-radius: 3px;
    padding: 1px 3px;
    min-width: 1.8ch;
    text-align: center;
    font-variant-numeric: tabular-nums lining-nums;
    transition: background 0.12s, color 0.12s, box-shadow 0.12s;
    cursor: pointer;
    letter-spacing: 0;
}

/* Active/focused segment — gothic purple highlight */
.seg.active {
    background: rgba(100, 25, 210, 0.38);
    color: rgba(215, 165, 255, 0.97);
    box-shadow: 0 0 0 1px rgba(170, 80, 255, 0.65),
                inset 0 0 8px rgba(120, 40, 220, 0.18);
    outline: none;
}

/* Year segment is wider */
.seg:last-child:not(:first-child) {
    min-width: 3.5ch;
}

/* ── Segmented input row: [widget] + [native picker trigger] ────────────────
   position:relative is required so the absolutely-positioned native input
   (opacity:0, 1×1px) is contained and doesn't affect surrounding layout.    */
.seg-input-row {
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 6px;
    width: 100%;
}

/* seg-input inside a row stretches to fill remaining space */
.seg-input-row .seg-input {
    flex: 1;
    width: auto;
}

/* weektime row: the seg-input-row (wrapping the time seg-input) must also flex */
.weektime-row .seg-input-row {
    flex: 1;
}

/* Calendar / clock picker trigger button */
.seg-picker-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    padding: 0;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-muted);
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background var(--transition);
}
.seg-picker-btn:hover {
    border-color: var(--border-mid);
    color: var(--accent-hover);
    background: var(--accent-soft);
}
.seg-picker-btn:active {
    background: rgba(120, 40, 240, 0.25);
    transform: scale(0.94);
}
.seg-picker-btn svg {
    width: 16px;
    height: 16px;
    pointer-events: none;
}

/* ── Segmented input clear button ────────────────────────────────────────────
   Sits between the seg-input and the picker-btn. Smaller than the picker (32px
   vs 36px), danger-accented on hover — matches IC.deadlineClear visual language. */
.seg-clear-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    padding: 0;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-muted);
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background var(--transition);
}
.seg-clear-btn:hover {
    border-color: rgba(220, 40, 70, 0.45);
    color: var(--prio-high);
    background: var(--prio-high-bg);
}
.seg-clear-btn:active {
    background: rgba(200, 30, 60, 0.22);
    transform: scale(0.94);
}
.seg-clear-btn svg {
    width: 14px;
    height: 14px;
    pointer-events: none;
}

/* ===================================================
   PAGE TRANSITION — GOTHIC VEIL DISSOLVE
   Outgoing page: rises and fades (the stone lifted).
   Incoming page: descends through a purple veil.
   Total duration ≈ 360ms. No jank — no layout shift.
   =================================================== */

@keyframes pageVeilOut {
    from { opacity: 1;   transform: translateY(0px)   scale(1); }
    to   { opacity: 0;   transform: translateY(-10px) scale(0.988); }
}

@keyframes pageVeilIn {
    from { opacity: 0;   transform: translateY(8px)  scale(0.993); filter: brightness(0.55) saturate(0.4); }
    to   { opacity: 1;   transform: translateY(0)    scale(1);     filter: brightness(1)    saturate(1); }
}

/* Applied by JS during transition */
#main-page.page-out,
#archive-page.page-out,
#notes-page.page-out {
    animation: pageVeilOut 0.20s var(--ease-sink) forwards;
    pointer-events: none;
}

#main-page.page-in,
#archive-page.page-in,
#notes-page.page-in {
    animation: pageVeilIn var(--dur-standard) var(--ease-gothic) forwards;
}

/* Nav tab active indicator gets a short glow pulse on switch */
@keyframes tabActivePulse {
    0%   { box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.30), 0 0 0   rgba(120, 40, 220, 0); }
    50%  { box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.55), 0 0 20px rgba(120, 40, 220, 0.30); }
    100% { box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.30), 0 0 12px rgba(120, 40, 220, 0.15); }
}

.nav-tab.active {
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.30), rgba(80, 15, 180, 0.20));
    color: var(--accent-hover);
    box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.30), 0 0 12px rgba(120, 40, 220, 0.15);
    font-weight: 600;
    text-shadow: 0 0 10px rgba(160, 90, 255, 0.4);
}

.nav-tab.tab-just-activated {
    animation: tabActivePulse 0.45s ease forwards;
}

/* Reduced motion — instant cut */
@media (prefers-reduced-motion: reduce) {
    #main-page.page-out,
    #archive-page.page-out,
    #notes-page.page-out,
    #main-page.page-in,
    #archive-page.page-in,
    #notes-page.page-in {
        animation: none !important;
    }
    .nav-tab.tab-just-activated { animation: none !important; }
}

/* ============================================================
   BATCH 6 — NEW FEATURES
   ============================================================ */

/* ── Sort mode button overridden indicator in group ─────────── */
.btn-group-sort.sort-overridden {
    opacity: 1;
    color: var(--accent);
    border-color: rgba(160, 80, 255, 0.4);
}

/* ── Group focus mode ────────────────────────────────────────── */
.group-section.group-focused > .group-header {
    box-shadow: 0 0 0 1px rgba(160, 80, 255, 0.35);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
}

/* ── Archive search ──────────────────────────────────────────── */
/* Full-width row below the title+buttons — flex-basis:100% forces a new row */
.archive-search-wrap {
    flex-basis: 100%;
    display: flex;
    align-items: center;
    gap: 9px;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    padding: 9px 14px;
    order: 10;  /* always last in the flex row */
    /* P2: smooth collapse when the archive is empty (search has nothing to search) */
    max-height: 60px;
    overflow: hidden;
    transition: border-color var(--transition),
                max-height var(--dur-standard) var(--ease-gothic),
                opacity var(--dur-standard) var(--ease-gothic),
                padding var(--dur-standard) var(--ease-gothic),
                margin var(--dur-standard) var(--ease-gothic),
                border-width var(--dur-standard) var(--ease-gothic);
}
.archive-search-wrap.is-hidden {
    max-height: 0;
    opacity: 0;
    padding-top: 0;
    padding-bottom: 0;
    margin: 0;
    border-width: 0;
    pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
    .archive-search-wrap { transition: border-color var(--transition); }
}
/* no highlight on focus — clean, unobtrusive */
.archive-search-wrap:focus-within {
    border-color: rgba(160, 80, 255, 0.75);
    box-shadow: 0 0 0 2px rgba(110, 30, 210, 0.15);
}
.archive-search-wrap svg {
    width: 14px;
    height: 14px;
    color: var(--text-muted);
    flex-shrink: 0;
}
#archive-search-box {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    font-family: var(--font-main);
    font-size: 14px;
    color: var(--text-primary);
}
#archive-search-box:focus-visible { outline: none; box-shadow: none; }
#archive-search-box:focus,
#archive-search-box:focus-visible { outline: none !important; box-shadow: none !important; }
#archive-search-box::placeholder { color: var(--text-muted); font-style: italic; }

/* ── Color filter modal ──────────────────────────────────────── */
.modal-color-filter { min-width: 280px; max-width: 380px; }
.modal-color-filter .modal-title {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #c060ff;
}
.modal-color-filter .modal-title svg { color: #c060ff; }
.color-filter-swatches {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    padding: 12px 0 4px;
    min-height: 44px;
}
.color-filter-swatch {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(255,255,255,0.12);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.15s, border-color 0.15s;
}
.color-filter-swatch:hover { transform: scale(1.12); border-color: rgba(255,255,255,0.45); }
.color-filter-swatch.active { border: 2px solid rgba(255,255,255,0.9); transform: scale(1.08); }
/* Clear button — gothic crossed swords icon */
.color-filter-clear {
    background: rgba(20, 5, 55, 0.8) !important;
    border: 1px solid rgba(160, 80, 255, 0.35) !important;
    color: rgba(200, 150, 255, 0.75);
}
.color-filter-clear svg { width: 14px; height: 14px; }
.color-filter-clear:hover {
    color: #e060a0;
    border-color: rgba(220, 60, 120, 0.6) !important;
}
.color-filter-empty {
    font-family: var(--font-label);
    font-size: 10px;
    letter-spacing: 1px;
    color: var(--text-muted);
    text-transform: uppercase;
    opacity: 0.6;
    padding: 4px 0;
}

/* ── Import choice modal ─────────────────────────────────────── */
.import-choice-modal {
    max-width: 380px;
}
.import-choice-desc {
    font-size: 15px;
    color: var(--text-muted);
    margin: 8px 0 18px;
    line-height: 1.5;
}
/* Three choices (Отмена · Добавить · Заменить) must stay on ONE row — the inherited
   flex-wrap was dropping «Заменить» to a second line at the old width. */
.import-choice-actions {
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: nowrap;
}
.import-choice-actions .btn-modal-cancel,
.import-choice-actions .btn-modal-confirm,
.import-choice-actions .btn-modal-danger {
    padding: 7px 13px;
    white-space: nowrap;
}

/* ── Idea 6: templates ───────────────────────────────────────── */
.btn-templates svg { width: 11px; height: 11px; }
.modal-templates { width: 400px; }
.templates-list {
    display: flex; flex-direction: column; gap: 6px;
    margin-bottom: 16px; max-height: 52vh; overflow-y: auto;
    scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent;
}
.templates-empty {
    font-family: var(--font-label); font-size: 11px; letter-spacing: 1px;
    color: var(--text-muted); text-transform: uppercase; opacity: 0.6;
    padding: 16px 4px; text-align: center;
}
.template-item { display: flex; align-items: stretch; gap: 6px; }
.template-create {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; gap: 5px;
    padding: 9px 12px; text-align: left;
    background: var(--bg-input); border: 1px solid var(--border);
    border-radius: var(--radius-sm); color: var(--text-primary);
    cursor: pointer; transition: all var(--transition); font-family: var(--font-main);
}
.template-create:hover { border-color: var(--border-mid); background: var(--accent-dim); }
.template-name { font-size: 14px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.template-meta { display: flex; flex-wrap: wrap; gap: 5px; }
.tpl-bit {
    display: inline-flex; align-items: center; gap: 3px;
    font-family: var(--font-label); font-size: 9px; letter-spacing: 0.5px;
    text-transform: uppercase; color: var(--text-muted);
    background: var(--bg-tag); border: 1px solid var(--border);
    border-radius: 99px; padding: 1px 7px;
}
.tpl-bit svg { width: 9px; height: 9px; }
.tpl-bit.tpl-prio-high   { color: var(--prio-high); }
.tpl-bit.tpl-prio-medium { color: var(--prio-medium); }
.tpl-bit.tpl-prio-low    { color: var(--prio-low); }
.template-del {
    flex-shrink: 0; width: 36px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: transparent; color: var(--text-muted); cursor: pointer;
    display: flex; align-items: center; justify-content: center; transition: all var(--transition);
}
.template-del svg { width: 15px; height: 15px; }
.template-del:hover { background: var(--prio-high-bg); color: var(--prio-high); border-color: var(--prio-high-border); }

/* ── P-C: backup / restore points ────────────────────────────── */
.modal-backups { width: 420px; }
.backups-desc {
    font-size: 12.5px; color: var(--text-muted);
    margin: 6px 0 16px; line-height: 1.5;
}
.backup-list {
    display: flex; flex-direction: column; gap: 6px;
    margin-bottom: 16px; max-height: 52vh; overflow-y: auto;
    scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent;
}
.backups-empty {
    font-family: var(--font-label); font-size: 11px; letter-spacing: 1px;
    color: var(--text-muted); text-transform: uppercase; opacity: 0.6;
    padding: 20px 4px; text-align: center;
}
.backup-restore {
    width: 100%;
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 9px 13px; text-align: left;
    background: var(--bg-input); border: 1px solid var(--border);
    border-radius: var(--radius-sm); color: var(--text-primary);
    cursor: pointer; transition: all var(--transition); font-family: var(--font-main);
}
.backup-restore:hover { border-color: var(--border-mid); background: var(--accent-dim); }
.backup-when { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.backup-age  { font-size: 13.5px; font-weight: 500; }
.backup-stamp {
    font-family: var(--font-label); font-size: 9.5px; letter-spacing: 0.5px;
    color: var(--text-muted); text-transform: uppercase;
}
.backup-meta { display: flex; flex-wrap: wrap; gap: 5px; justify-content: flex-end; flex-shrink: 0; }
.backup-bit {
    display: inline-flex; align-items: center;
    font-family: var(--font-label); font-size: 9px; letter-spacing: 0.5px;
    text-transform: uppercase; color: var(--text-muted);
    background: var(--bg-tag); border: 1px solid var(--border);
    border-radius: 99px; padding: 1px 7px;
}

/* ── P-D: bulk group picker ──────────────────────────────────── */
.modal-bulk-group { width: 360px; }
.bulk-group-list {
    display: flex; flex-wrap: wrap; gap: 8px;
    margin-bottom: 16px; max-height: 50vh; overflow-y: auto;
    scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent;
}
.bulk-group-pill {
    cursor: pointer; border-width: 1px; border-style: solid;
    font-family: var(--font-main); font-size: 13px;
    transition: filter var(--transition), background var(--transition);
}
.bulk-group-pill:hover { filter: brightness(1.25); }
.bulk-group-none {
    background: var(--bg-input); color: var(--text-muted);
    border-color: var(--border); border-radius: 99px; padding: 3px 12px;
}
.bulk-group-none:hover { background: var(--accent-dim); color: var(--text-primary); }

/* ── Bulk priority buttons — box comes from .sb-btn; this only owns the dot ──── */
.prio-bulk-btn .prio-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; box-shadow: 0 0 5px currentColor; }
.prio-bulk-btn .prio-dot.prio-high   { background: var(--prio-high);   color: var(--prio-high); }
.prio-bulk-btn .prio-dot.prio-medium { background: var(--prio-medium); color: var(--prio-medium); }
.prio-bulk-btn .prio-dot.prio-low    { background: var(--prio-low);    color: var(--prio-low); }

/* ============================================================
   BATCH 7 — SUBTASK SPLIT, MONTHLY REPEAT, FORM ANCHORS,
               FORM SUBTASK ACTIONS
   ============================================================ */

/* ── Subtask split mode ──────────────────────────────────────── */
/* In split mode the outer UL becomes a flex column of section blocks */
.subtask-list.sub-split-mode {
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* Both headers share base styles */
.sub-split-active-header,
.sub-split-done-header {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 6px 4px;
    cursor: pointer;
    user-select: none;
    font-family: var(--font-label);
    font-size: 9.5px;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--accent-hover);
    opacity: 0.9;
    transition: opacity 0.15s;
}
.sub-split-active-header:hover,
.sub-split-done-header:hover { opacity: 1; }
.sub-split-done-header {
    border-top: 1px solid rgba(255,255,255,0.05);
    margin-top: 3px;
}
/* Sword icons stay small */
.sub-split-active-header > svg:not(.sub-split-chevron),
.sub-split-done-header > svg:not(.sub-split-chevron) { width: 10px; height: 10px; flex-shrink: 0; }

/* Chevron rotates on collapse */
.sub-split-chevron {
    margin-left: auto; flex-shrink: 0;
    width: 10px; height: 10px;
    transition: transform 0.24s cubic-bezier(0.4, 0, 0.2, 1);
}
.sub-split-active-header.collapsed .sub-split-chevron,
.sub-split-done-header.collapsed   .sub-split-chevron { transform: rotate(180deg); }

/* Collapse wrappers animate via grid-template-rows */
.sub-split-active-wrap,
.sub-split-done-wrap {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic),
                opacity             var(--dur-collapse) var(--ease-gothic);
    opacity: 1;
    list-style: none;
    padding: 0; margin: 0;
}
.sub-split-active-wrap.collapsed,
.sub-split-done-wrap.collapsed {
    grid-template-rows: 0fr;
    opacity: 0;
    pointer-events: none;
}
/* Inner 2-column grid inside each wrap */
.sub-split-inner {
    overflow: hidden;
    min-height: 0;
    display: grid;
    /* minmax(0,1fr): keep columns equal and shrinkable so the right column's
       border is never clipped by this wrap's overflow:hidden. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3px;
    list-style: none;
    /* 2px right inset so the right column's edge stays inside this wrap's
       overflow:hidden and its outline isn't clipped. */
    padding: 0 2px 0 0; margin: 0;
}
/* Problem 6: a lone subtask in its split subgroup spans the full row width
   instead of leaving an empty right column. */
.sub-split-inner > .subtask-item:last-child:nth-child(odd) {
    grid-column: 1 / -1;
}
@media (prefers-reduced-motion: reduce) {
    .sub-split-active-wrap, .sub-split-done-wrap { transition: none; }
}

/* ── Repeat modal monthday stepper ───────────────────── */
/* Problem 1: the monthday stepper fills the whole anchor row so its right edge
   lines up with the time input below it (was capped at 160px = looked squeezed). */
.repeat-stepper-wrap {
    flex: 1;
    max-width: none;
    width: 100%;
}
.repeat-anchor-row {
    margin-top: 8px;
}

/* ── Inline form repeat anchor — gothic style matching the repeat modal ─── */
.form-repeat-anchor {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
    margin-top: 6px;
    background: rgba(15, 5, 45, 0.6);
    border: 1px solid rgba(140, 60, 255, 0.2);
    border-radius: var(--radius-sm);
}
.form-anchor-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}
/* SegmentedInput row inside the form anchor inherits full available width */
.form-anchor-row .seg-input-row { flex: 1; }
.form-anchor-row .seg-input { flex: 1; width: 100%; }
.form-anchor-label {
    font-family: var(--font-label);
    font-size: 9px;
    letter-spacing: 1.2px;
    color: var(--accent-hover);
    text-transform: uppercase;
    white-space: nowrap;
    opacity: 0.85;
    min-width: 48px;
}
/* Form anchor inputs use exact same styles as the repeat modal components:
   - weekday select → mirrors .dl-month-trigger look
   - monthday number → mirrors .stepper-input (without stepper buttons for compactness)
   - time → handed off to SegmentedInput, styled by seg-input classes               */
.form-anchor-select {
    flex: 1;
    width: 100%;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    cursor: pointer;
    outline: none;
    transition: border-color var(--transition);
    -webkit-appearance: none;
    appearance: none;
    letter-spacing: 0.3px;
}
.form-anchor-select:hover { border-color: rgba(140, 60, 255, 0.5); color: var(--accent-hover); }
.form-anchor-select:focus { border-color: rgba(150, 70, 255, 0.55); }
/* Form weekday picker — inherits dl-weekday-picker styles, just needs flex:1 */
.form-wd-picker { flex: 1; min-width: 0; }
.form-wd-list   { z-index: 500; }
.form-anchor-number {
    flex: 1;
    text-align: center;
    border: none;
    border-left: 1px solid var(--border-input);
    border-right: 1px solid var(--border-input);
    background: transparent;
    font-size: 15px;
    padding: 9px 8px;
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-weight: 500;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
    -moz-appearance: textfield;
}
.form-anchor-number::-webkit-inner-spin-button,
.form-anchor-number::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.form-anchor-time { display: none; } /* replaced by SegmentedInput */

/* Form anchor stepper — compact version of modal stepper */
.form-anchor-stepper {
    flex: 1;
    min-height: 36px;
}
.form-anchor-stepper .stepper-btn {
    width: 32px;
    min-height: 36px;
}
.form-anchor-stepper .stepper-input {
    padding: 6px 4px;
    font-size: 14px;
}
.form-anchor-time { display: none; } /* replaced by SegmentedInput */

/* (P12) Old .form-sub-* item styles removed — the form now renders real
   .subtask-item rows that reuse the in-task subtask styles. */

/* ── Sort mode btn icons size ────────────────────────────────── */
#btn-sort-mode svg { width: 15px; height: 15px; }

/* ============================================================
   ГРИМУАР (NOTES PAGE) — п11
   «Иллюминированный кодекс»: сегмент Записи/Склеп, master–detail
   (оглавление + страница-манускрипт), отдельный архив заметок.
   Готик-палитра, рукотворные SVG, без emoji.
   ============================================================ */

/* ── top bar: segment (Записи/Склеп) + «Начертать» ── */
.grim-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 14px;
}
.grim-segment {
    display: inline-flex;
    gap: 3px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 4px;
}
.grim-seg {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 14px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-family: var(--font-label);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    border-radius: calc(var(--radius-md) - 4px);
    cursor: pointer;
    transition: all var(--transition);
}
.grim-seg svg { width: 14px; height: 14px; }
.grim-seg:hover { color: var(--text-secondary); }
.grim-seg.active {
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.30), rgba(80, 15, 180, 0.20));
    color: var(--accent-hover);
    box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.30), 0 0 12px rgba(120, 40, 220, 0.15);
    text-shadow: 0 0 10px rgba(160, 90, 255, 0.4);
}
.grim-seg-count {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 16px; height: 15px; padding: 0 4px;
    font-family: var(--font-label); font-size: 9px; font-weight: 700; letter-spacing: 0;
    color: var(--text-muted); background: rgba(0,0,0,0.35);
    border: 1px solid var(--border); border-radius: 99px;
}

.grim-new-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.28), rgba(80, 15, 180, 0.16));
    color: var(--accent-hover);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-md);
    padding: 9px 16px;
    font-family: var(--font-label);
    font-size: 11.5px;
    letter-spacing: 1px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all var(--transition);
}
.grim-new-btn:hover { border-color: var(--border-bright); box-shadow: 0 0 16px rgba(120, 40, 220, 0.28); color: var(--text-primary); }
.grim-new-btn svg { width: 14px; height: 14px; }

/* п.12: split «Начертать» — primary btn + template trigger + popover */
.grim-new-split { position: relative; display: inline-flex; align-items: stretch; flex-shrink: 0; }
.grim-new-split .grim-new-btn { border-radius: var(--radius-md) 0 0 var(--radius-md); border-right: none; }
.grim-tpl-trigger {
    display: inline-flex; align-items: center; justify-content: center; width: 40px;
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.18), rgba(80, 15, 180, 0.10));
    color: var(--accent); border: 1px solid var(--border-mid);
    border-radius: 0 var(--radius-md) var(--radius-md) 0; cursor: pointer;
    transition: all var(--transition); position: relative;
}
.grim-tpl-trigger::before { content: ""; position: absolute; left: 0; top: 22%; bottom: 22%; width: 1px; background: var(--border); }
/* animated two-state book: clasped tome (menu closed) ⇄ open tome (menu open),
   crossfaded — same idiom as the note-fold toggle (.gf-open / .gf-closed). */
.grim-tpl-trigger .gt-ic { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; transition: opacity var(--dur-standard) var(--ease-gothic); }
.grim-tpl-trigger .gt-open { opacity: 0; }
.grim-new-split.open .grim-tpl-trigger .gt-closed { opacity: 0; }
.grim-new-split.open .grim-tpl-trigger .gt-open { opacity: 1; }
.grim-tpl-trigger svg { width: 21px; height: 21px; }
.grim-tpl-trigger:hover { color: var(--text-primary); border-color: var(--border-bright); box-shadow: 0 0 16px rgba(120, 40, 220, 0.28); }
.grim-new-split.open .grim-tpl-trigger { color: var(--accent-hover); border-color: var(--border-bright); background: var(--accent-soft); }

.grim-tpl-pop {
    position: absolute; top: calc(100% + 8px); right: 0; width: 322px; z-index: 60;
    background: var(--bg-modal); border: 1px solid var(--border-mid); border-radius: var(--radius-md);
    box-shadow: 0 18px 48px rgba(2, 0, 12, 0.7), 0 0 0 1px rgba(120, 60, 220, 0.08);
    overflow: hidden; transform-origin: top right;
    opacity: 0; transform: translateY(-10px) scale(0.94); pointer-events: none;
    transition: opacity 0.2s var(--ease-emerge), transform 0.22s var(--ease-emerge);
}
.grim-new-split.open .grim-tpl-pop { opacity: 1; transform: none; pointer-events: auto; }
.grim-tpl-head { font-family: var(--font-label); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--text-secondary); padding: 12px 15px 8px; border-bottom: 1px solid var(--border); }
.grim-tpl-sect { font-family: var(--font-label); font-size: 9.5px; letter-spacing: 1.8px; text-transform: uppercase; color: var(--accent-hover); opacity: 0.92; padding: 10px 15px 4px; }
.grim-tpl-item { display: flex; align-items: center; gap: 12px; padding: 10px 15px; cursor: pointer; transition: background var(--transition); border-left: 2px solid transparent; }
.grim-tpl-item:hover { background: var(--bg-item-hover); border-left-color: var(--accent); }
.grim-tpl-ic { flex: none; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; color: var(--accent-hover); background: var(--accent-soft); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.grim-tpl-ic svg { width: 22px; height: 22px; }
.grim-tpl-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.grim-tpl-name { font-family: var(--font-label); font-size: 12px; letter-spacing: 0.4px; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.grim-tpl-desc { font-size: 13.5px; color: var(--text-muted); font-style: italic; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.grim-tpl-item.user .grim-tpl-ic { color: var(--text-secondary); }
.grim-tpl-del { flex: none; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; color: var(--text-muted); opacity: 0; transition: all var(--transition); border-radius: var(--radius-xs); background: transparent; border: none; cursor: pointer; }
.grim-tpl-item.user:hover .grim-tpl-del { opacity: 0.6; }
.grim-tpl-del:hover { color: var(--prio-high); opacity: 1; }
.grim-tpl-del svg { width: 15px; height: 15px; }
.grim-tpl-divline { height: 1px; background: var(--border); margin: 6px 0; opacity: 0.6; }

/* п.13: «Перенос» (import/export) — reuses the .grim-tpl-pop popover visuals */
.grim-io-split { position: relative; display: inline-flex; }
.grim-io-btn svg { width: 17px; height: 17px; }
.grim-io-sel { position: relative; display: inline-flex; align-items: center; }
.grim-io-split.open .grim-tpl-pop,
.grim-io-sel.open .grim-tpl-pop { opacity: 1; transform: none; pointer-events: auto; }
.grim-io-sel-pop { right: 0; }
/* select bar is position:static (.main-select-bar) + backdrop-filter → its stacking
   context is covered by the later-painted .grim-layout, hiding the export popover.
   Lift it above the list so the popover is solid and clickable. */
.grim-select-bar { position: relative; z-index: 40; }

/* ── search ── */
/* NA-10: the search pill + colour-filter button share one row. */
.grim-search-row {
    display: flex;
    align-items: stretch;
    gap: 10px;
    margin-bottom: 20px;
}
.grim-search-wrap {
    position: relative;   /* NA-13: anchor for the in-pill clear button */
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 9px;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-md);
    padding: 9px 14px;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.grim-search-wrap:focus-within {
    border-color: var(--border-bright);
    box-shadow: 0 0 14px rgba(120, 40, 220, 0.18);
}
.grim-search-wrap svg { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; }
.grim-search-wrap input {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-primary);
    font-family: var(--font-main);
    font-size: 15px;
    /* NOT italic on the field — italic glyphs + tight padding clipped the caret and
       the first character at the field start ("начало поиска съедает курсор"). */
    font-style: normal;
    caret-color: var(--accent-hover);
    /* A hair of left padding so the first glyph's left bearing + the Home caret +
       a selection starting at char 0 aren't clipped by the input's content edge. */
    padding-left: 3px;
    /* The rounded pill is the WRAPPER's job; the input must stay square — otherwise
       its own border-radius clips the selection box into a rounded left edge. */
    border-radius: 0;
    /* NA-13: keep a long query from running under the absolute clear button. */
    padding-right: 22px;
}
.grim-search-wrap input::placeholder { color: var(--text-muted); opacity: 0.85; font-style: italic; }

/* NA-13: clear button — lives inside the search pill (shares its background, no
   bordered box), crossed-daggers glyph. Hidden while empty; slides + fades out from
   the field's right edge once there's a query (driven purely by :placeholder-shown). */
.grim-search-x {
    position: absolute;
    right: 11px;
    top: 50%;
    transform: translateY(-50%) scale(0.78);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition), transform var(--transition), color var(--transition);
}
.grim-search-wrap input:not(:placeholder-shown) ~ .grim-search-x {
    opacity: 1;
    transform: translateY(-50%) scale(1);
    pointer-events: auto;
}
.grim-search-x:hover { color: var(--accent-hover); }
/* Override the generic `.grim-search-wrap svg { color: var(--text-muted) }` so the
   glyph inherits the button's colour (and therefore the hover tint). */
.grim-search-x svg { width: 14px; height: 14px; display: block; color: inherit; }
@media (prefers-reduced-motion: reduce) { .grim-search-x { transition: color var(--transition); } }

/* #3 (порт NA-13 в DUSK): тот же ✕-кинжалы внутри пилюли поиска — основной тулбар и
   архив. Делит фон поля (без отдельной рамки), выезжает+гаснет от правого края, когда
   есть запрос (чистый :placeholder-shown, без JS на показ/скрытие). */
.search-wrap, .archive-search-wrap { position: relative; }
.search-wrap #search-box,
.archive-search-wrap #archive-search-box { padding-right: 22px; }
.search-x {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%) scale(0.78);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition), transform var(--transition), color var(--transition);
}
.search-wrap input:not(:placeholder-shown) ~ .search-x,
.archive-search-wrap input:not(:placeholder-shown) ~ .search-x {
    opacity: 1;
    transform: translateY(-50%) scale(1);
    pointer-events: auto;
}
.search-x:hover { color: var(--accent-hover); }
.search-x svg { width: 14px; height: 14px; display: block; color: inherit; }
@media (prefers-reduced-motion: reduce) { .search-x { transition: color var(--transition); } }

/* NA-10: colour-filter — a crystal button beside the search pill + a swatch popover. */
.grim-cfilter { position: relative; flex: 0 0 auto; }
.grim-cfilter-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 100%;
    min-height: 40px;
    padding: 0;
    background: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    cursor: pointer;
    transition: border-color var(--transition), box-shadow var(--transition), color var(--transition);
}
.grim-cfilter-btn svg { width: 19px; height: 19px; display: block; }
.grim-cfilter-btn:hover { color: var(--accent-hover); border-color: var(--border-bright); }
.grim-cfilter-btn.active {
    color: var(--accent-hover);
    border-color: var(--accent);
    box-shadow: 0 0 12px rgba(120, 40, 220, 0.28), inset 0 0 8px rgba(120, 40, 220, 0.16);
}
.grim-cfilter.open .grim-cfilter-btn { border-color: var(--border-bright); color: var(--accent-hover); }

/* Popover: drops below the button, right-aligned, gothic panel. Hugs its content
   (width:max-content) so a 2-colour set has no empty gutter and the clear button sits
   in the same row as the swatches — every cell is the same 36px square, evenly gapped. */
.grim-cfilter-pop {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 60;
    width: max-content;
    max-width: 224px;   /* ~5 swatches before wrapping */
    padding: 9px;
    background: var(--bg-elevated, var(--bg-input));
    border: 1px solid var(--border-bright);
    border-radius: var(--radius-md);
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55), 0 0 16px rgba(120, 40, 220, 0.16);
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-content: flex-start;
    gap: 9px;
    opacity: 0;
    transform: translateY(-6px) scale(0.97);
    transform-origin: top right;
    pointer-events: none;
    transition: opacity var(--transition), transform var(--transition);
}
.grim-cfilter-pop .color-filter-swatch { flex: 0 0 auto; margin: 0; }
.grim-cfilter.open .grim-cfilter-pop {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.grim-cfilter-empty {
    margin: 0;
    font-family: var(--font-label);
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
@media (prefers-reduced-motion: reduce) {
    .grim-cfilter-pop { transition: opacity var(--transition); transform: none; }
    .grim-cfilter.open .grim-cfilter-pop { transform: none; }
}

/* ── master–detail layout (codex spread) ── */
.grim-layout {
    /* Flex (not grid) so the list's flex-basis can animate px↔% — grid tracks won't
       interpolate px↔fr, which made the collapse snap. The detail is the flexible
       filler; driving the list width smoothly resizes the page each frame. */
    display: flex;
    gap: 22px;
    align-items: flex-start;
    transition: gap var(--dur-ritual) var(--ease-gothic);
}
/* When a record is open, auto-narrow the list so the page gets room (desktop only). */
@media (min-width: 641px) {
    /* When a record is open, auto-narrow the list so the page gets room. */
    .grim-layout.show-detail .grim-list { flex-basis: 198px; }
    /* Focus mode — collapse the list to a titles-only rail, give the page near-full width. */
    .grim-layout.grim-focus.show-detail .grim-list { flex-basis: 138px; }
    .grim-layout.grim-focus.show-detail .grim-leaf-s,
    .grim-layout.grim-focus.show-detail .grim-leaf-d { display: none; }
    .grim-layout.grim-focus.show-detail .grim-leaf { padding: 8px 9px 8px 11px; }
    .grim-layout.grim-focus.show-detail .grim-leaf-t { font-size: 13px; }
    .grim-layout.grim-focus.show-detail .grim-list-head { font-size: 9px; letter-spacing: 1px; }
    .grim-layout.grim-focus.show-detail .grim-sort-trigger { font-size: 9px; padding: 2px 3px 2px 5px; }
    /* Full mode — list shrinks to zero width, the page fills the container. */
    .grim-layout.grim-full.show-detail { gap: 0; }
    .grim-layout.grim-full.show-detail .grim-list { flex-basis: 0; overflow: hidden; min-width: 0; opacity: 0; pointer-events: none; }
    /* Collapsed mode — the list grows to full width while the NOTE pane shrinks to zero
       (selection kept). flex-basis animates px↔% so the widths interpolate smoothly;
       the detail also fades + sinks so the reflow is masked. Re-click the open entry to toggle. */
    .grim-layout.grim-note-collapsed.show-detail { gap: 0; }
    .grim-layout.grim-note-collapsed.show-detail .grim-list { flex-basis: 100%; }
    .grim-layout.grim-note-collapsed.show-detail .grim-detail {
        overflow: hidden; min-width: 0; padding-left: 0; border-left: none;
        opacity: 0; transform: translateX(16px) scale(0.985); pointer-events: none;
        /* Collapse animates toward this state → fade that "sinks" away while the pane
           narrows; opacity leads (shorter) so reflow is masked before the width finishes. */
        transition: opacity var(--dur-standard) var(--ease-sink), transform var(--dur-ritual) var(--ease-sink);
    }
}
/* Focus toggle — corner button on the page (desktop only; mobile uses the back button instead). */
.grim-focus-toggle {
    position: absolute; top: 6px; right: 12px; z-index: 2;
    width: 30px; height: 30px; display: none;
    align-items: center; justify-content: center;
    border-radius: 50%; border: 1px solid var(--border);
    background: var(--bg-item); color: var(--text-secondary);
    cursor: pointer; transition: all var(--transition);
}
.grim-focus-toggle svg { width: 18px; height: 18px; transition: opacity var(--dur-quick) var(--ease-gothic); }
.grim-focus-toggle:hover { border-color: var(--border-bright); color: var(--accent-hover); }
.grim-focus-toggle.on { color: var(--accent-hover); border-color: var(--border-bright); }
@media (min-width: 641px) { .grim-focus-toggle { display: inline-flex; } }

/* Toolbar manual control — corner button beside the focus toggle (shown on every
   viewport: touch has no hover, so the manual show/hide is essential there). */
.grim-bar-toggle {
    position: absolute; top: 42px; right: 12px; z-index: 2;
    width: 30px; height: 30px; display: inline-flex;
    align-items: center; justify-content: center;
    border-radius: 50%; border: 1px solid var(--border);
    background: var(--bg-item); color: var(--text-secondary);
    cursor: pointer; transition: all var(--transition);
}
.grim-bar-toggle svg { width: 18px; height: 18px; }
.grim-bar-toggle:hover { border-color: var(--border-bright); color: var(--accent-hover); }
.grim-bar-toggle.on { color: var(--accent-hover); border-color: var(--border-bright); box-shadow: 0 0 10px var(--accent-glow); }

/* ── п.14: Table of contents (TOC) — corner toggle + sticky right rail ── */
.grim-toc-toggle {
    position: absolute; top: 78px; right: 12px; z-index: 2;
    width: 30px; height: 30px; display: none;
    align-items: center; justify-content: center;
    border-radius: 50%; border: 1px solid var(--border);
    background: var(--bg-item); color: var(--text-secondary);
    cursor: pointer; transition: all var(--transition);
}
.grim-toc-toggle svg { width: 18px; height: 18px; }
.grim-toc-toggle:hover { border-color: var(--border-bright); color: var(--accent-hover); }
.grim-toc-toggle.on { color: var(--accent-hover); border-color: var(--border-bright); box-shadow: 0 0 10px var(--accent-glow); }
/* Button only appears on notes with enough structure (≥3 headings), desktop only. */
@media (min-width: 641px) { .grim-page.toc-avail .grim-toc-toggle { display: inline-flex; } }
/* Crypt (read-only) has no toolbar toggle in the stack — close the gap. */
.grim-page--ro .grim-toc-toggle { top: 42px; }

/* Content + rail sit side by side once the TOC opens. .grim-page-main always wraps the
   content (transparent when the rail is closed: .grim-page stays a plain block). */
.grim-page-main { position: relative; }
.grim-page.toc-open { display: flex; align-items: flex-start; }
.grim-page.toc-open .grim-page-main { flex: 1 1 0; min-width: 0; }

/* The rail is position:sticky itself (NOT wrapped in an overflow ancestor — that would
   capture the sticky and pin it to the page instead of the viewport). overflow lives on
   the rail, so its own slide-clip doesn't break stickiness. */
/* Outer = slide/clip layer only (sticky so the card follows the scroll); it carries
   no frame of its own, so the card inside reads as one autonomous object. */
.grim-toc {
    position: sticky; top: 74px; align-self: flex-start;
    flex: 0 0 0; width: 0; opacity: 0; overflow: hidden;
    pointer-events: none;
    transition: flex-basis var(--dur-ritual) var(--ease-gothic),
                width var(--dur-ritual) var(--ease-gothic),
                opacity var(--dur-standard) var(--ease-gothic);
}
.grim-page.toc-open .grim-toc { flex-basis: 222px; width: 222px; opacity: 1; pointer-events: auto; }
/* The visible card — a self-framed codex index, detached from the note page and lifted
   by a drop shadow. Capped height + internal scroll keep the frame closed on every edge
   while reading (no open bottom/right when the page scrolls). */
/* Frame only — same fill/brightness as the note page (var(--bg-input)). overflow:hidden
   clips the inner scrollbar to the rounded corners (no square corner spill). */
.grim-toc-inner {
    width: 200px; box-sizing: border-box;
    margin: 4px 8px 18px 14px;
    overflow: hidden;
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    box-shadow: 0 16px 34px -16px rgba(0, 0, 0, 0.9),
                inset 0 1px 0 rgba(170, 90, 255, 0.12);
}
/* Scroll container lives inside the clipped frame; its scrollbar can't reach the corners. */
.grim-toc-scroll {
    max-height: calc(100vh - 116px);
    overflow-y: auto; overscroll-behavior: contain;
    padding: 0 0 12px;
}
.grim-toc-scroll::-webkit-scrollbar { width: 7px; }
.grim-toc-scroll::-webkit-scrollbar-thumb { background: var(--border-mid); border-radius: 4px; }
.grim-toc-scroll::-webkit-scrollbar-track { background: transparent; }
.grim-toc-scroll { scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent; }
/* Header stays pinned at the card's top as the index scrolls under it. Same fill as the
   note; an accent label + underline give it a crown without changing brightness. */
.grim-toc-head {
    position: sticky; top: 0; z-index: 1;
    display: flex; align-items: center; gap: 7px;
    font-family: var(--font-label); text-transform: uppercase;
    letter-spacing: 1.6px; font-size: 10px; color: var(--accent-hover);
    padding: 12px 10px 9px 16px; margin-bottom: 6px;
    border-bottom: 1px solid var(--border-mid);
    background: var(--bg-input);
}
.grim-toc-head > svg { width: 14px; height: 14px; color: var(--accent); opacity: 0.85; }
/* In-panel collapse — reuses the app's "close panel" crossed-swords glyph (as in find). */
.grim-toc-close {
    margin-left: auto; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; padding: 0;
    background: transparent; border: 1px solid transparent; border-radius: 6px;
    color: var(--text-secondary); cursor: pointer;
    transition: color var(--transition), background var(--transition), border-color var(--transition);
}
/* display:block kills the inline-svg baseline gap that was offsetting the glyph. */
.grim-toc-close svg { display: block; width: 14px; height: 14px; }
.grim-toc-close:hover { color: var(--accent-hover); background: var(--accent-soft); border-color: var(--border); }
.grim-toc-nav { display: flex; flex-direction: column; }
.grim-toc-item {
    position: relative;
    display: flex; align-items: flex-start; gap: 8px;
    width: 100%; text-align: left;
    background: transparent; border: none; cursor: pointer;
    color: var(--accent-hover); font-family: var(--font-main);
    font-size: 12.5px; line-height: 1.3; padding: 5px 12px 5px 16px;
    transition: color var(--transition), background var(--transition);
}
.grim-toc-item:hover { color: var(--grim-heading); background: var(--accent-soft); }
.grim-toc-item.l2 { padding-left: 30px; font-size: 11.5px; color: var(--text-secondary); opacity: 0.96; }
.grim-toc-item.l3 { padding-left: 44px; font-size: 11px; color: var(--text-secondary); opacity: 0.78; }
.grim-toc-item .gtoc-gl {
    flex: 0 0 9px; display: inline-flex; align-items: center; justify-content: center;
    margin-top: 3px; color: var(--accent); opacity: 0.7;
}
.grim-toc-item .gtoc-gl svg { width: 9px; height: 9px; }
.grim-toc-item:not(.l1) .gtoc-gl::before {
    content: ''; width: 3px; height: 3px; border-radius: 50%; background: currentColor;
}
.grim-toc-item .gtoc-tx { word-break: break-word; overflow-wrap: anywhere; }
.grim-toc-item.active { color: var(--grim-heading); }
.grim-toc-item.active .gtoc-gl { opacity: 1; color: var(--accent-hover); }
.grim-toc-item.active::before {
    content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2.5px;
    border-radius: 2px; background: var(--accent); box-shadow: 0 0 8px var(--accent-glow);
}
/* Smooth-scroll target clears the top chrome; brief illumination on jump. */
.grim-body h1, .grim-body h2, .grim-body h3 { scroll-margin-top: 84px; }
.grim-body h1.grim-toc-flash, .grim-body h2.grim-toc-flash, .grim-body h3.grim-toc-flash {
    animation: grimTocFlash 1.2s var(--ease-gothic);
}
@keyframes grimTocFlash {
    0%   { background: rgba(160, 90, 255, 0.26); border-radius: 4px; }
    100% { background: transparent; }
}
/* Mobile: no rail (too narrow) — page stays a plain block. */
@media (max-width: 640px) {
    .grim-page.toc-open { display: block; }
    .grim-toc { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    .grim-toc { transition: opacity var(--dur-quick) linear; }
    .grim-body h1.grim-toc-flash, .grim-body h2.grim-toc-flash, .grim-body h3.grim-toc-flash { animation: none; }
}

/* ============================================================
   п.15 — ЛЕТОПИСЬ (version history modal)
   ============================================================ */
.grim-hist-ov {
    position: fixed; inset: 0; z-index: 4000;
    display: flex; align-items: center; justify-content: center; padding: 28px;
    background: rgba(4, 1, 14, 0.66); backdrop-filter: blur(3px);
    opacity: 0; pointer-events: none;
    transition: opacity var(--dur-standard) var(--ease-gothic);
}
.grim-hist-ov.open { opacity: 1; pointer-events: auto; }
.grim-hist-modal {
    display: flex; flex-direction: column;
    width: min(960px, 95vw); height: min(680px, 88vh);
    background: var(--bg-input);
    border: 1px solid var(--border-mid); border-radius: var(--radius-lg, 14px);
    box-shadow: 0 30px 80px -24px rgba(0, 0, 0, 0.92), inset 0 1px 0 rgba(170, 90, 255, 0.12);
    overflow: hidden;
    transform: translateY(14px) scale(0.985);
    transition: transform var(--dur-ritual) var(--ease-gothic);
}
.grim-hist-ov.open .grim-hist-modal { transform: none; }
.grim-hist-bar {
    flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
    padding: 13px 14px 13px 18px; border-bottom: 1px solid var(--border-mid);
    background: linear-gradient(180deg, rgba(110, 40, 200, 0.10), transparent);
}
.grim-hist-title {
    display: flex; align-items: center; gap: 9px; margin-right: auto;
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 2px;
    font-size: 12px; color: var(--accent-hover);
}
.grim-hist-title svg { width: 18px; height: 18px; color: var(--accent); }
.grim-hist-x {
    display: flex; align-items: center; justify-content: center; width: 30px; height: 30px;
    padding: 0; border: 1px solid transparent; border-radius: 8px;
    background: transparent; color: var(--text-secondary); cursor: pointer;
    transition: color var(--transition), background var(--transition), border-color var(--transition);
}
.grim-hist-x svg { width: 18px; height: 18px; display: block; }
.grim-hist-x:hover { color: var(--accent-hover); background: var(--accent-soft); border-color: var(--border); }
.grim-hist-cols { flex: 1 1 auto; display: flex; min-height: 0; }
.grim-hist-list {
    flex: 0 0 252px; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    border-right: 1px solid var(--border-mid); padding: 8px 0 14px;
    scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent;
}
.grim-hist-list::-webkit-scrollbar { width: 7px; }
.grim-hist-list::-webkit-scrollbar-thumb { background: var(--border-mid); border-radius: 4px; }
.grim-hist-sect {
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 1.4px;
    font-size: 9.5px; color: var(--text-secondary); opacity: 0.8;
    padding: 12px 16px 6px;
}
.grim-hist-sect.back { color: var(--accent-hover); opacity: 0.95; }
.grim-hist-item {
    position: relative; display: flex; flex-direction: column; gap: 2px;
    width: 100%; text-align: left; cursor: pointer;
    background: transparent; border: none; border-left: 2.5px solid transparent;
    padding: 7px 14px 8px 16px;
    transition: background var(--transition), border-color var(--transition);
}
.grim-hist-item:hover { background: var(--accent-soft); }
.grim-hist-item.active { background: var(--accent-soft); border-left-color: var(--accent); }
.grim-hist-item.active::after {
    content: ''; position: absolute; left: 0; top: 6px; bottom: 6px; width: 2.5px;
    background: var(--accent); box-shadow: 0 0 8px var(--accent-glow);
}
.grim-hist-when {
    display: flex; align-items: center; gap: 7px;
    font-size: 12px; color: var(--accent-hover); font-family: var(--font-main);
}
.grim-hist-item.active .grim-hist-when { color: var(--grim-heading); }
.grim-hist-tag {
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.8px;
    font-size: 8.5px; padding: 1px 6px; border-radius: 999px; line-height: 1.5;
}
.grim-hist-tag.now { color: #d9f7e0; background: rgba(70, 180, 110, 0.22); border: 1px solid rgba(90, 200, 130, 0.4); }
.grim-hist-tag.back { color: var(--accent-hover); background: var(--accent-soft); border: 1px solid var(--border-mid); }
.grim-hist-ttl {
    font-size: 13px; color: var(--text-secondary); font-family: var(--font-main);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.grim-hist-item.active .grim-hist-ttl { color: var(--text-primary, #e6d4ff); }
.grim-hist-sub { font-size: 10.5px; color: var(--text-secondary); opacity: 0.62; }
.grim-hist-empty { padding: 14px 16px; font-size: 12px; color: var(--text-secondary); opacity: 0.6; }
.grim-hist-empty.big {
    margin: auto; text-align: center; line-height: 1.7; font-size: 13.5px;
    color: var(--text-secondary); opacity: 0.7; padding: 40px;
}
.grim-hist-pv { flex: 1 1 0; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.grim-hist-pv-head {
    flex: 0 0 auto; display: flex; align-items: center; gap: 12px;
    padding: 14px 20px; border-bottom: 1px solid var(--border-mid);
}
.grim-hist-pv-when {
    display: flex; align-items: center; gap: 8px; margin-right: auto;
    font-size: 13px; color: var(--accent-hover); font-family: var(--font-main);
}
.grim-hist-pv-when svg { width: 17px; height: 17px; color: var(--accent); opacity: 0.85; }
.grim-hist-cur {
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 1.2px;
    font-size: 10px; color: var(--text-secondary); opacity: 0.7;
}
.grim-hist-restore {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 7px 14px; border: 1px solid var(--border-mid); border-radius: var(--radius-md);
    background: var(--accent-soft); color: var(--accent-hover); cursor: pointer;
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 1.2px; font-size: 11px;
    transition: all var(--transition);
}
.grim-hist-restore svg { width: 16px; height: 16px; }
.grim-hist-restore:hover {
    border-color: var(--border-bright); color: var(--grim-heading);
    box-shadow: 0 0 14px var(--accent-glow);
}
.grim-hist-pv-body {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    padding: 18px 24px 28px; cursor: default;
    scrollbar-width: thin; scrollbar-color: var(--border-mid) transparent;
}
.grim-hist-pv-body::-webkit-scrollbar { width: 8px; }
.grim-hist-pv-body::-webkit-scrollbar-thumb { background: var(--border-mid); border-radius: 4px; }
.grim-hist-pv-title {
    flex: 0 0 auto; padding: 16px 24px 0; font-family: var(--font-display, var(--font-main));
    font-size: 19px; color: var(--grim-heading); line-height: 1.25;
}
.grim-hist-pv-title.untitled { opacity: 0.5; font-style: italic; }
.grim-hist-blank { color: var(--text-secondary); opacity: 0.5; font-style: italic; }
/* Mobile: stack list over preview. */
@media (max-width: 720px) {
    .grim-hist-cols { flex-direction: column; }
    .grim-hist-list { flex: 0 0 40%; border-right: none; border-bottom: 1px solid var(--border-mid); }
}
@media (prefers-reduced-motion: reduce) {
    .grim-hist-ov, .grim-hist-modal { transition: opacity var(--dur-quick) linear; }
    .grim-hist-ov.open .grim-hist-modal { transform: none; }
}

.grim-detail {
    position: relative; padding-left: 22px; border-left: 1px solid var(--border); min-height: 320px;
    flex: 1 1 0; min-width: 0;   /* flexible filler — shrinks to 0 as the list grows to full */
    /* Expand (collapse class removed) animates toward this state → unhurried "veil-lift". */
    transform: translateX(0) scale(1);
    transition: opacity var(--dur-ritual) var(--ease-emerge), transform var(--dur-ritual) var(--ease-emerge);
}
/* NA-4 (option 3): while folding/unfolding a note whose .grim-page width is pinned in px
   (so the heavy body never re-flows — see grimToggleCollapse), the pane must clip the
   fixed-width page instead of letting it overflow to the right. Held from collapse until
   the expand settles, then removed with the pin. */
.grim-detail.grim-pin { overflow: hidden; }
.grim-list {
    display: flex; flex-direction: column; gap: 7px;
    flex: 0 0 244px; min-width: 0;   /* flex item in the layout; width driven below */
    transition: flex-basis var(--dur-ritual) var(--ease-gothic);
}
.grim-list-head {
    position: relative;
    display: flex; align-items: center; gap: 8px;
    font-family: var(--font-label); font-size: 10.5px; letter-spacing: 1.5px;
    text-transform: uppercase; color: var(--text-muted); padding: 0 2px 8px;
}
/* Count label never wraps — it shares the row with the sort control. */
.grim-list-head > span { white-space: nowrap; flex-shrink: 0; }
/* Divider is a full-width underline (was a dim growing bar between the two that also
   squeezed the count onto a second line). Always visible, steals no horizontal space. */
.grim-list-head::after {
    content: ''; position: absolute; left: 2px; right: 2px; bottom: 0; height: 1px;
    background: linear-gradient(90deg,
        rgba(150,70,240,0.60) 0%, rgba(146,66,236,0.34) 30%, rgba(140,60,230,0.18) 50%,
        rgba(146,66,236,0.34) 70%, rgba(150,70,240,0.60) 100%);
}
/* п.7: compact sort dropdown, pushed to the head's right edge. */
.grim-sort { flex-shrink: 0; margin-left: auto; }
.grim-sort-trigger {
    display: inline-flex; align-items: center; gap: 5px;
    background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm);
    color: var(--text-muted); cursor: pointer; padding: 2px 5px 2px 7px;
    font-family: var(--font-label); font-size: 10px; letter-spacing: 1px; text-transform: uppercase;
    transition: color var(--transition), border-color var(--transition), background var(--transition);
}
.grim-sort-trigger:hover { color: var(--accent-hover); border-color: var(--border); background: var(--accent-soft); }
.dl-month-picker.open .grim-sort-trigger { color: var(--accent-hover); border-color: var(--border-mid); }
.grim-sort-cur { white-space: nowrap; }
/* Right-anchored, content-width popup (the shared rule stretches it full-width otherwise). */
.grim-sort .dl-month-list { left: auto; right: 0; min-width: 150px; }
.grim-sort .dl-month-option { font-size: 13px; padding: 8px 14px; }

/* NA-11: task sort picker — icon trigger (toolbar + per-group). On open the list is
   PORTALED to <body> (JS) so it escapes transformed ancestors / overflow clips / stacking
   contexts — task rows and groups can never paint over it. Styles hang off the list's own
   .task-sort-list class (not a .task-sort ancestor) so they survive the move. */
.task-sort.dl-month-picker { position: relative; display: inline-flex; }
.task-sort-list {
    position: fixed;
    left: auto;
    /* Explicit shrink-to-content — a fixed element with left:auto + right:Npx otherwise
       blows up to a huge used width and spills off the left edge. */
    width: max-content;
    min-width: 162px;
    max-width: 240px;
    z-index: 1500;
    padding: 4px;
    /* Elegant, restrained: near-black violet, a thin amethyst hairline, one soft shadow. */
    background: linear-gradient(168deg, #0d0622 0%, #08041a 100%);
    border: 1px solid rgba(150, 85, 255, 0.30);
    border-radius: var(--radius-md);
    box-shadow: 0 14px 32px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(170, 110, 255, 0.10);
}
/* Visible + animated only while portaled open (the shared .dl-month-list keeps it at
   opacity:0 otherwise; we don't use the in-picker .open state for task sort). */
.task-sort-list.task-sort-portal {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    animation: sortPortalIn var(--dur-quick) var(--ease-emerge);
}
@keyframes sortPortalIn {
    from { opacity: 0; transform: translateY(-6px) scaleY(0.97); }
    to   { opacity: 1; transform: none; }
}
.task-sort-list .dl-month-option {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13px;
    padding: 7px 11px;
    border-radius: 7px;
    white-space: nowrap;
}
.task-sort-list .dl-month-option .tso-ic {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    transition: color var(--dur-micro);
}
.task-sort-list .dl-month-option .tso-ic svg { width: 15px; height: 15px; }
.task-sort-list .dl-month-option .tso-label { flex: 1; }
.task-sort-list .dl-month-option:hover .tso-ic { color: var(--accent-hover); }
/* Active row: a slim left "ember" bar + tinted glyph (matches the app's priority ember). */
.task-sort-list .dl-month-option.active {
    box-shadow: inset 2px 0 0 var(--accent);
}
.task-sort-list .dl-month-option.active .tso-ic { color: var(--accent-hover); }
/* The global toolbar picker (#task-sort-list) reads as a primary control → a touch larger
   than the compact per-group pickers. (The id survives the body-portal.) */
#task-sort-list { min-width: 180px; padding: 5px; }
#task-sort-list .dl-month-option { font-size: 13.5px; gap: 10px; padding: 8px 12px; border-radius: 8px; }
#task-sort-list .dl-month-option .tso-ic { width: 17px; height: 17px; }
#task-sort-list .dl-month-option .tso-ic svg { width: 16px; height: 16px; }
@media (prefers-reduced-motion: reduce) {
    .task-sort-list.task-sort-portal { animation: none; }
}
.grim-list-none {
    font-size: 14px; font-style: italic; color: var(--text-muted);
    padding: 16px 4px; text-align: center; opacity: 0.85;
}

/* cross-app #8: crypt (note archive) month sections — mirror the task archive, styled to
   the grimoire rail (label font, gothic violet hairline). The crypt has no DnD/sort, so
   these sections are purely a chronological grouping by archived month. */
.grim-crypt-month { margin-top: 10px; }
.grim-crypt-month:first-child { margin-top: 2px; }
.grim-crypt-month-head {
    position: relative;
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 4px 2px 7px; background: transparent; border: none; cursor: pointer;
    font-family: var(--font-label); font-size: 10px; letter-spacing: 1.3px;
    text-transform: uppercase; color: var(--text-muted);
    transition: color var(--transition-slow);
}
.grim-crypt-month-head::after {           /* same hairline violet divider as the list head */
    content: ''; position: absolute; left: 2px; right: 2px; bottom: 0; height: 1px;
    background: linear-gradient(90deg,
        rgba(150,70,240,0.45) 0%, rgba(146,66,236,0.20) 50%, rgba(150,70,240,0.45) 100%);
}
.grim-crypt-month-head:hover { color: var(--text-secondary); }
.grim-crypt-month-name { flex: 1; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.grim-crypt-month-count {
    flex-shrink: 0; font-size: 9px; opacity: 0.55; font-weight: 600; letter-spacing: 0.5px;
    background: var(--bg-item); border: 1px solid var(--border); border-radius: 99px; padding: 1px 7px;
}
.grim-crypt-month-chevron {
    width: 13px; height: 13px; flex-shrink: 0; opacity: 0.7;
    transition: transform var(--transition-slow), opacity var(--transition-slow);
}
.grim-crypt-month-head:hover .grim-crypt-month-chevron { opacity: 1; }
.grim-crypt-month.collapsed .grim-crypt-month-chevron { transform: rotate(-90deg); }
/* Clean grid-rows collapse (0fr↔1fr) — smooth, no JS height measuring. */
.grim-crypt-month-body {
    display: grid; grid-template-rows: 1fr;
    transition: grid-template-rows var(--dur-collapse) var(--ease-gothic);
}
.grim-crypt-month.collapsed .grim-crypt-month-body { grid-template-rows: 0fr; }
.grim-crypt-month-inner { overflow: hidden; min-height: 0; }

/* ── list entry ("leaf") ── */
.grim-leaf {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 8px;
    width: 100%;
    text-align: left;
    background: var(--bg-item);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 11px 11px 10px 15px;
    cursor: pointer;
    overflow: hidden;
    font-family: var(--font-main);
    box-shadow: inset 0 0 0 1px transparent;
    transition: background var(--transition), border-color var(--transition),
                box-shadow var(--transition), transform var(--transition);
}
.grim-leaf::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 2px;
    background: linear-gradient(180deg, rgba(130,50,220,0.30), rgba(90,30,180,0.10));
    transition: background var(--transition), box-shadow var(--transition);
}
.grim-leaf:hover { background: var(--bg-item-hover); border-color: var(--border-mid); transform: translateX(2px); }
.grim-leaf:hover::before { background: linear-gradient(180deg, var(--border-bright), rgba(120,40,220,0.30)); box-shadow: 0 0 8px rgba(120,40,220,0.30); }
.grim-leaf.active {
    background: linear-gradient(135deg, rgba(110, 30, 220, 0.26), rgba(80, 15, 180, 0.13));
    border-color: var(--border-mid);
    box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.22), 0 0 18px rgba(110, 35, 215, 0.12);
}
.grim-leaf.active::before { background: linear-gradient(180deg, var(--accent), #7030d0); box-shadow: 0 0 12px var(--accent-glow); }
/* п.5 pin: a pinned record floats to the top of the grimoire wearing the same forged
   spike + brightened bar + soft glow as a pinned task — one consistent "fixed" motif. */
.grim-leaf.pinned {
    background: linear-gradient(100deg, rgba(120, 40, 220, 0.10) 0%, transparent 34%), var(--bg-item);
    box-shadow: -2px 0 12px rgba(140, 50, 255, 0.16);
}
.grim-leaf.pinned::before { background: linear-gradient(180deg, rgba(180, 100, 255, 0.85), #7030d0); box-shadow: 0 0 10px var(--accent-glow); }
.grim-leaf.pinned.active { background: linear-gradient(135deg, rgba(110, 30, 220, 0.26), rgba(80, 15, 180, 0.13)); }   /* active wash wins, spike + bar persist */
.grim-leaf-spike {
    position: absolute; top: 1px; left: 1px; width: 17px; height: 17px;
    color: var(--accent-hover); pointer-events: none; z-index: 4;
    filter: drop-shadow(0 0 4px rgba(160, 96, 255, 0.55));
    animation: pinSpikeIn 0.34s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.grim-leaf-spike svg { width: 100%; height: 100%; display: block; }
.grim-leaf-main { display: flex; flex-direction: column; flex: 1; min-width: 0; }
/* 1b: select-mode checkbox + ticked-row highlight (mirrors the task select look). */
.grim-leaf-check {
    display: flex; align-items: center; justify-content: center;
    width: 22px; flex-shrink: 0; margin-top: 1px;
    color: var(--text-dim, rgba(180,140,255,0.4));
    transition: color var(--transition), transform var(--transition);
}
.grim-leaf-check svg { width: 18px; height: 18px; display: block; }
.grim-leaf--select.selected { background: rgba(100, 30, 200, 0.12); border-color: rgba(160, 80, 255, 0.35); }
.grim-leaf--select.selected::before { background: linear-gradient(180deg, var(--accent), #7030d0); box-shadow: 0 0 10px var(--accent-glow); }
.grim-leaf--select.selected .grim-leaf-check { color: rgba(200, 130, 255, 0.95); transform: scale(1.06); }
.grim-leaf-t {
    font-size: 16px; font-weight: 700; color: var(--grim-heading); line-height: 1.3;
    text-shadow: 0 0 10px var(--accent-glow);
    word-break: break-word; overflow-wrap: anywhere;
}
.grim-leaf.active .grim-leaf-t { text-shadow: 0 0 14px var(--accent-glow); }
.grim-leaf.untitled .grim-leaf-t { font-style: italic; color: var(--text-muted); font-weight: 400; }
.grim-leaf-s {
    font-size: 13px; font-style: italic; color: var(--text-muted);
    margin-top: 3px; line-height: 1.35;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    word-break: break-word;
}
.grim-leaf-d {
    display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
    font-family: var(--font-label); font-size: 9.5px; letter-spacing: 1px;
    text-transform: uppercase; color: var(--text-muted); margin-top: 7px; opacity: 0.72;
}
.grim-leaf-d svg { width: 11px; height: 11px; flex-shrink: 0; color: var(--accent-hover); opacity: 0.85; }
/* Fold affordance on the open entry — a gothic tome that opens/closes. Two stacked
   glyphs crossfade by the collapse state. Desktop only (mobile uses the back button). */
.grim-leaf-fold {
    display: none; position: relative; align-self: center; flex-shrink: 0;
    width: 16px; height: 16px; margin-left: 2px;
}
@media (min-width: 641px) { .grim-leaf.active .grim-leaf-fold { display: block; } }
.grim-leaf-fold .gf-open,
.grim-leaf-fold .gf-closed {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    color: var(--text-muted); opacity: 0.5;
    transition: opacity var(--dur-standard) var(--ease-gothic), color var(--transition);
}
.grim-leaf-fold .gf-closed { opacity: 0; }
.grim-leaf-fold svg { width: 14px; height: 14px; }
/* collapsed → clasped tome shows, open tome hides */
.grim-layout.grim-note-collapsed .grim-leaf.active .grim-leaf-fold .gf-open { opacity: 0; }
.grim-layout.grim-note-collapsed .grim-leaf.active .grim-leaf-fold .gf-closed { opacity: 0.5; }
/* hover brightens whichever glyph is currently shown */
.grim-leaf.active:hover .grim-leaf-fold .gf-open,
.grim-layout.grim-note-collapsed .grim-leaf.active:hover .grim-leaf-fold .gf-closed { opacity: 1; color: var(--accent-hover); }

.grim-leaf mark, .grim-page mark { background: rgba(160, 90, 255, 0.32); color: var(--text-primary); border-radius: 2px; padding: 0 1px; }

/* C: structure glyph standing in for a block (table/quote/code/list/checklist) inside
   a list snippet — V3 treatment: accent-tinted, no box, baseline-aligned in the run. */
.grim-snip-ic { display: inline-flex; width: 13px; height: 13px; vertical-align: -2px; margin: 0 3px; color: var(--accent-hover); opacity: 0.9; }
.grim-snip-ic svg { width: 100%; height: 100%; }

/* A: in-note find highlights — painted via the CSS Custom Highlight API, so they never
   touch the editable DOM (nothing persisted to note.body). Current match glows brighter. */
::highlight(grim-find)     { background-color: rgba(160, 90, 255, 0.30); color: var(--text-primary); }
::highlight(grim-find-cur) { background-color: rgba(210, 120, 255, 0.58); color: #fff; }

/* A: floating find bar — fixed at the viewport bottom-centre (body-level singleton so a
   transformed .grim-page can't break its fixed positioning). Counter + prev/next + close. */
.grim-find {
    position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%) translateY(8px);
    display: inline-flex; align-items: center; gap: 2px; z-index: 60;
    background: rgba(20, 14, 32, 0.94); border: 1px solid var(--border-mid); border-radius: 9px;
    padding: 5px 7px; box-shadow: 0 8px 26px rgba(0, 0, 0, 0.5), 0 0 16px rgba(120, 40, 220, 0.16);
    backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
    opacity: 0; pointer-events: none;
    transition: opacity var(--dur-quick) var(--ease-gothic), transform var(--dur-quick) var(--ease-gothic);
}
.grim-find.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.grim-find .gf-cnt { font-family: var(--font-label); font-size: 11px; letter-spacing: 1px; color: var(--text-secondary); padding: 0 8px; white-space: nowrap; }
.grim-find .gf-cnt b { color: var(--accent-hover); font-weight: 700; }
.grim-find .gf-btn {
    width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid transparent; border-radius: 5px; color: var(--text-muted); cursor: pointer;
    background: none; transition: all var(--transition);
}
.grim-find .gf-btn:hover { color: var(--accent-hover); border-color: var(--border-bright); background: var(--accent-soft); }
.grim-find .gf-btn svg { width: 15px; height: 15px; }
.grim-find .gf-next svg { transform: rotate(180deg); }   /* sword points down = next */
.grim-find .gf-close svg { width: 14px; height: 14px; }
.grim-find .gf-sep { width: 1px; height: 16px; background: var(--border-mid); margin: 0 3px; }
@media (prefers-reduced-motion: reduce) { .grim-find { transition: opacity var(--dur-quick) linear; } }

/* staggered entrance for list entries */
@keyframes grimLeafIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: translateY(0); } }
.grim-leaf.gl-in { animation: grimLeafIn 0.4s var(--ease-emerge) both; animation-delay: calc(var(--i, 0) * 42ms); }

/* ── detail placeholder ── */
.grim-detail-empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 16px; padding: 70px 20px; text-align: center;
    border: 1px dashed var(--border); border-radius: var(--radius-md);
    color: var(--text-muted);
}
.grim-detail-empty-ic svg { width: 48px; height: 48px; color: var(--accent); opacity: 0.45; filter: drop-shadow(0 0 9px var(--accent-glow)); }
.grim-detail-empty p { font-size: 15px; font-style: italic; }

/* ── the manuscript page (illuminated) ── */
.grim-page {
    position: relative;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-mid);
    background-color: var(--bg-input);
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='34' viewBox='0 0 32 32' fill='none' stroke='%23a060ff' stroke-width='1.4' stroke-linecap='round'%3E%3Cpath d='M4 28 C4 14 14 4 28 4' stroke-opacity='0.5'/%3E%3Cpath d='M4 28 C10 24 12 18 12 12 C18 12 24 8 26 4' stroke-opacity='0.3'/%3E%3Ccircle cx='28' cy='4' r='1.5' fill='%23a060ff' fill-opacity='0.55' stroke='none'/%3E%3Ccircle cx='4' cy='28' r='1.5' fill='%23a060ff' fill-opacity='0.55' stroke='none'/%3E%3C/svg%3E"),
        linear-gradient(180deg, rgba(120, 86, 40, 0.10), rgba(70, 48, 22, 0.03));
    background-repeat: no-repeat, no-repeat;
    background-position: left 12px top 12px, center;
    background-size: 30px 30px, auto;
    box-shadow: inset 0 0 0 1px rgba(150, 70, 255, 0.10), inset 0 0 50px rgba(60, 8, 140, 0.10);
    /* Incoming note materialises — used when switching records (renderGrimDetail rebuilds
       the page). The outgoing page sinks first via .grim-page--leaving (see grimOpen). */
    animation: grimPageIn var(--dur-ritual) var(--ease-emerge) both;
}
@keyframes grimPageIn { from { opacity: 0; transform: translateY(14px) scale(0.994); } to { opacity: 1; transform: none; } }
/* Outgoing page on a note→note switch — sink up + fade before the new one is rendered. */
.grim-page--leaving {
    animation: none;
    opacity: 0; transform: translateY(-9px) scale(0.994); pointer-events: none;
    transition: opacity 0.15s var(--ease-sink), transform 0.15s var(--ease-sink);
}

.grim-title-in, .grim-title-ro {
    width: 100%;
    background: transparent;
    border: none;
    outline: none;
    color: var(--grim-heading);
    font-family: var(--font-title);
    font-size: 26px;
    font-weight: 800;
    letter-spacing: 1px;
    line-height: 1.2;
    /* uppercase for EVERY script — Cinzel only caps Latin, so Cyrillic/other
       layouts need the transform to match. */
    text-transform: uppercase;
    text-shadow: 0 0 18px var(--accent-glow), 0 0 6px rgba(170, 90, 255, 0.5), 0 2px 3px rgba(0, 0, 0, 0.45);
    /* right pad clears the corner button column (buttons now stack vertically → ~42px) */
    padding: 16px 42px 10px 52px;
    word-break: break-word;
    overflow-wrap: anywhere;
    /* title is now a <textarea> so long titles wrap (an <input> can't) — kill the
       resize grip + the scrollbar; JS auto-grows the height to fit. */
    resize: none;
    overflow: hidden;
    display: block;
}
.grim-title-in::placeholder { color: var(--text-muted); opacity: 0.6; font-weight: 400; }
/* Flourish divider — two CSS lines flanking a perfectly-centred ornament
   (flex:1 on both sides guarantees the diamond sits dead-centre at any width). */
.grim-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 4px 22px 8px 52px;
}
.grim-divider::before, .grim-divider::after { content: ''; flex: 1; height: 1px; }
.grim-divider::before { background: linear-gradient(90deg, transparent, rgba(150, 70, 255, 0.45)); }
.grim-divider::after  { background: linear-gradient(90deg, rgba(150, 70, 255, 0.45), transparent); }
.grim-fleur { flex: 0 0 auto; display: inline-flex; color: var(--accent); filter: drop-shadow(0 0 5px var(--accent-glow)); }
.grim-fleur svg { display: block; width: 40px; height: 12px; }
.grim-body {
    font-family: var(--font-main);
    font-size: 15.5px;
    color: var(--text-secondary);
    line-height: 1.62;
    padding: 4px 20px 18px 52px;
    min-height: 250px;
    word-break: break-word;
    overflow-wrap: anywhere;
    outline: none;
    cursor: text;
    -webkit-user-select: text;
    user-select: text;
}
.grim-body--ro { cursor: default; min-height: 120px; }
.grim-body:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
    font-style: italic;
    opacity: 0.7;
    pointer-events: none;
}
.grim-body a, .grim-leaf a, .grim-body--ro a { color: var(--text-link); }
.grim-body ::selection, .grim-body::selection { background: rgba(150, 70, 255, 0.30); }

/* ── formatted body elements (shared by editor + read-only) ── */
.grim-body p, .grim-body--ro p { margin: 0 0 9px; }
.grim-body h1, .grim-body--ro h1 {
    font-family: var(--font-title); font-size: 23px; font-weight: 800; color: var(--grim-heading);
    letter-spacing: 0.6px; margin: 16px 0 8px; text-shadow: 0 0 16px var(--accent-glow), 0 0 4px rgba(170,90,255,0.45);
    padding-bottom: 5px; border-bottom: 1px solid var(--border-mid);
}
.grim-body h2, .grim-body--ro h2 {
    font-family: var(--font-title); font-size: 19px; font-weight: 800; color: var(--grim-heading);
    letter-spacing: 0.6px; margin: 14px 0 6px; text-shadow: 0 0 13px var(--accent-glow);
}
.grim-body h3, .grim-body--ro h3 {
    font-family: var(--font-title); font-size: 16px; font-weight: 700; color: var(--grim-heading);
    letter-spacing: 0.5px; margin: 12px 0 4px; text-shadow: 0 0 10px var(--accent-glow);
}
/* ── Tables (этап 2): light ledger grid WITH vertical rules, accent-underlined
   header. Lean lines so the table doesn't out-shout the prose. ─────────────── */
.grim-body table, .grim-body--ro table {
    border-collapse: collapse; width: 100%; margin: 14px 0;
    font-family: var(--font-main); font-size: 1em; color: var(--text-secondary);
}
.grim-body th, .grim-body td, .grim-body--ro th, .grim-body--ro td {
    border: 1px solid var(--border); padding: 7px 11px;
    text-align: left; vertical-align: top; min-width: 44px;
}
/* body cells read as purple prose; the header outranks them by treatment
   (label face, caps, tracking, glow, weight) — not merely by being brighter. */
.grim-body tbody td, .grim-body--ro tbody td { color: var(--text-secondary); }
.grim-body thead th, .grim-body--ro thead th {
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.8px;
    font-weight: 700; color: var(--grim-heading); font-size: 0.85em;
    border-bottom: 2px solid var(--border-bright);
    text-shadow: 0 0 9px var(--accent-glow), 0 0 2px rgba(170, 90, 255, 0.5);
}
.grim-body tbody tr:hover, .grim-body--ro tbody tr:hover { background: rgba(255, 255, 255, 0.022); }
/* п.13: per-column alignment (left = default). */
.grim-body th.align-c, .grim-body td.align-c, .grim-body--ro th.align-c, .grim-body--ro td.align-c { text-align: center; }
.grim-body th.align-r, .grim-body td.align-r, .grim-body--ro th.align-r, .grim-body--ro td.align-r { text-align: right; }

/* Size-grid popover for inserting a table. */
.grim-table-pop {
    position: fixed; z-index: 1200; background: var(--bg-input);
    border: 1px solid var(--border-mid); border-radius: var(--radius-sm);
    padding: 12px; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.6);
}
.gtp-grid { display: grid; grid-template-columns: repeat(8, 19px); grid-auto-rows: 19px; gap: 4px; }
.gtp-c {
    border: 1px solid var(--border); border-radius: 2px; background: var(--bg-item); cursor: pointer;
    transition: background 0.08s ease, border-color 0.08s ease, box-shadow 0.08s ease;
}
.gtp-c.hot { border-color: var(--border-bright); background: var(--accent-soft); box-shadow: 0 0 6px var(--accent-glow); }
.gtp-lbl {
    margin-top: 9px; text-align: center; font-family: var(--font-label); text-transform: uppercase;
    letter-spacing: 1px; font-size: 12px; color: var(--accent-hover);
}

/* ── Table structure-edit overlay — explicit wax-seal toggle (M2) + click-to-open
   floating menus on column/row gutters (the v3 synthesis). Lives in .grim-page so
   it scrolls glued, takes no flow space, never persists into note.body. The caret
   never triggers it: clicking a cell to edit its text stays quiet. ───────────── */
.grim-tctl { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.grim-tctl:not(.on) { display: none; }
.grim-tctl > * { pointer-events: auto; }

/* wax-seal sigil at each table's top-right corner (idle: faint ring; on: bloom) */
.gtc-seal {
    position: absolute; width: 30px; height: 30px; padding: 0; transform: translate(-50%, -50%);
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%; cursor: pointer; color: rgba(200, 150, 255, 0.72);
    background: rgba(20, 8, 52, 0.22); border: 1px solid var(--border-mid);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
    opacity: 0; pointer-events: none;   /* hidden until its table is hovered (or in edit mode) */
    transition: opacity 0.18s ease, color 0.24s var(--ease-emerge), background 0.24s var(--ease-emerge), border-color 0.24s var(--ease-emerge), box-shadow 0.24s var(--ease-emerge), transform 0.24s var(--ease-emerge);
}
.gtc-seal.gtc-show { opacity: 1; pointer-events: auto; }
.gtc-seal:hover { color: var(--accent-hover); border-color: var(--border-bright); box-shadow: 0 0 12px var(--accent-glow); transform: translate(-50%, -50%) scale(1.06); }
.gtc-seal.on {
    color: #fff; border-color: var(--border-bright);
    background: radial-gradient(circle at 38% 34%, rgba(74, 30, 146, 0.98), rgba(24, 10, 60, 0.98));
    box-shadow: 0 0 20px var(--accent-glow), inset 0 1px 4px rgba(210, 160, 255, 0.4);
}
/* even (30−18)/2 = 6px margins → centred on whole pixels at any devicePixelRatio
   (fractional Windows scaling biased the old 5.5px split left until :hover scale re-snapped it). */
.gtc-seal svg { width: 18px; height: 18px; display: block; }
.gtc-ring { position: absolute; inset: -4px; border-radius: 50%; border: 1px solid var(--border-bright); opacity: 0; transform: scale(0.8); transition: opacity 0.3s, transform 0.3s var(--ease-emerge); }
.gtc-seal.on .gtc-ring { opacity: 0.45; transform: scale(1); }

/* edit-mode frame around the active table */
.gtc-frame {
    position: absolute; border-radius: 5px; pointer-events: none;
    box-shadow: 0 0 0 1px var(--border-bright), 0 0 22px rgba(120, 40, 220, 0.22);
    background: rgba(120, 60, 220, 0.04); animation: gtcFade 0.25s var(--ease-emerge) both;
}
@keyframes gtcFade { from { opacity: 0; } to { opacity: 1; } }

/* gutter handles (only present in edit mode) */
.gtc-gut {
    position: absolute; display: flex; align-items: center; justify-content: center;
    cursor: pointer; color: var(--accent-hover); border-radius: 4px; border: 1px solid transparent;
    transition: color 0.14s ease, background 0.14s ease, border-color 0.14s ease;
    animation: gtcFade 0.2s var(--ease-emerge) both;
}
.gtc-colgut { height: 18px; background: linear-gradient(180deg, rgba(126, 56, 220, 0.22), rgba(126, 56, 220, 0.05)); }
.gtc-rowgut { width: 18px;  background: linear-gradient(90deg,  rgba(126, 56, 220, 0.22), rgba(126, 56, 220, 0.05)); }
.gtc-gut:hover, .gtc-gut.gtc-active { color: #fff; border-color: var(--border-mid); }
.gtc-colgut:hover, .gtc-colgut.gtc-active { background: linear-gradient(180deg, rgba(154, 84, 255, 0.60), rgba(154, 84, 255, 0.16)); }
.gtc-rowgut:hover, .gtc-rowgut.gtc-active { background: linear-gradient(90deg,  rgba(154, 84, 255, 0.60), rgba(154, 84, 255, 0.16)); }
.gtc-grip { display: flex; }
.gtc-grip svg { width: 18px; height: 18px; display: block; }

/* floating action menu opened by a gutter click */
.gtc-pop {
    position: absolute; display: flex; gap: 5px; padding: 5px; z-index: 6;
    background: var(--bg-input); border: 1px solid var(--border-mid); border-radius: var(--radius-sm);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.62); animation: gtcPop 0.16s var(--ease-emerge) both;
}
@keyframes gtcPop { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
.gtc-mbtn, .gtc-edge {
    width: 30px; height: 30px; padding: 0; display: flex; align-items: center; justify-content: center;
    background: var(--bg-input); border: 1px solid var(--border-mid); border-radius: var(--radius-xs);
    color: var(--accent-hover); cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition), transform var(--transition);
}
.gtc-mbtn svg, .gtc-edge svg { width: 18px; height: 18px; }
.gtc-mbtn:hover, .gtc-edge:hover { background: var(--accent-soft); border-color: var(--border-bright); color: #fff; transform: translateY(-1px); }
.gtc-mbtn.del { color: var(--text-secondary); }
.gtc-mbtn.del:hover { background: var(--prio-high-bg); border-color: var(--prio-high-border); color: var(--prio-high); }
/* п.13: divider before the align cluster + active align state */
.gtc-divline { align-self: stretch; width: 1px; margin: 2px 1px; background: linear-gradient(180deg, transparent, var(--border-bright), transparent); }
.gtc-align { color: var(--text-secondary); }
.gtc-align.on { color: var(--grim-heading); border-color: rgba(160, 96, 255, 0.55); background: var(--accent-soft); box-shadow: 0 0 10px -2px var(--accent); }

/* edge rails: append a column (right) / row (bottom) */
.gtc-edge { position: absolute; transform: translate(-50%, -50%); box-shadow: 0 3px 12px rgba(0, 0, 0, 0.45);
    width: 27px; height: 27px; animation: gtcFade 0.2s var(--ease-emerge) both; }
.gtc-edge:hover { transform: translate(-50%, -50%) translateY(-1px); }

@media (prefers-reduced-motion: reduce) {
    .gtc-seal, .gtc-gut, .gtc-frame, .gtc-pop, .gtc-edge { animation: none; transition: none; }
}

/* Emphasis stays inside the violet palette — never near-white (--text-primary). */
.grim-body strong, .grim-body--ro strong, .grim-body b, .grim-body--ro b { color: var(--accent-hover); font-weight: 600; }
.grim-body em, .grim-body--ro em, .grim-body i, .grim-body--ro i { font-style: italic; color: var(--accent-hover); }
.grim-body a, .grim-body--ro a {
    text-decoration: underline; text-decoration-color: rgba(160,90,255,0.4); cursor: pointer;
    border-radius: 3px; padding: 0 1px; margin: 0 -1px;
    transition: color var(--transition), text-shadow var(--transition),
                background var(--transition), text-decoration-color var(--transition);
}
.grim-body a:hover, .grim-body--ro a:hover {
    color: var(--accent-hover); text-decoration-color: var(--accent);
    text-shadow: 0 0 8px var(--accent-glow); background: rgba(150, 70, 255, 0.14);
}
/* lists — one shared gutter so bullet / number / checkbox sit at the same x,
   and markers ride the text's own line-height so they share its baseline */
.grim-body ul, .grim-body ol, .grim-body--ro ul, .grim-body--ro ol { margin: 0 0 9px; padding-left: 0; list-style: none; }
.grim-body li, .grim-body--ro li { position: relative; margin: 3px 0; padding-left: 26px; }
/* bullet */
.grim-body ul:not(.task) li::before, .grim-body--ro ul:not(.task) li::before {
    content: ''; position: absolute; left: 6px; top: 0.72em; width: 5px; height: 5px;
    background: var(--accent); transform: rotate(45deg); box-shadow: 0 0 6px var(--accent-glow);
}
/* number — same font/size/line-height as the text → baseline matches exactly */
.grim-body ol, .grim-body--ro ol { counter-reset: gli; }
.grim-body ol li, .grim-body--ro ol li { counter-increment: gli; }
.grim-body ol li::before, .grim-body--ro ol li::before {
    content: counter(gli) '.'; position: absolute; left: 3px; top: 0.06em;
    line-height: inherit; font-size: inherit; font-family: var(--font-main);
    color: var(--accent-hover);
}
/* checklist */
.grim-body ul.task li::before, .grim-body--ro ul.task li::before {
    content: ''; position: absolute; left: 1px; top: 0.32em; width: 15px; height: 15px;
    background: none; transform: none; border: 1.5px solid var(--border-mid); border-radius: 3px; box-shadow: none;
    cursor: pointer;
}
.grim-body ul.task li.done, .grim-body--ro ul.task li.done {
    color: var(--text-muted); text-decoration: line-through; text-decoration-color: rgba(140,90,200,0.5);
}
.grim-body ul.task li.done::before, .grim-body--ro ul.task li.done::before {
    background: linear-gradient(135deg, #7030d0, #a060ff); border-color: var(--border-bright);
}
.grim-body ul.task li.done::after, .grim-body--ro ul.task li.done::after {
    content: ''; position: absolute; left: 6px; top: calc(0.32em + 2px); width: 5px; height: 8px;
    border: solid var(--text-primary); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.grim-body blockquote, .grim-body--ro blockquote {
    position: relative; margin: 10px 0; padding: 6px 14px; border-left: 2px solid var(--accent);
    background: rgba(110, 30, 210, 0.08); color: var(--text-secondary); font-style: italic; border-radius: 0 4px 4px 0;
}
.grim-body blockquote::before, .grim-body--ro blockquote::before {
    content: '\201C'; position: absolute; right: 8px; top: -6px; font-family: var(--font-title);
    font-size: 34px; color: var(--accent); opacity: 0.18; pointer-events: none;
}
.grim-body code, .grim-body--ro code {
    /* inline-block → one rectangular container; long code wraps INSIDE instead of
       fragmenting into open-edged inline pieces. Backticks flank it (markdown-authentic). */
    display: inline-block; max-width: 100%; vertical-align: bottom;
    font-family: var(--font-mono); font-size: 13px;
    background: rgba(120, 50, 210, 0.13); border-radius: 3px;
    padding: 1px 5px; color: var(--accent-hover);
    overflow-wrap: anywhere; word-break: break-word;
}
.grim-body code::before, .grim-body code::after,
.grim-body--ro code::before, .grim-body--ro code::after {
    content: '\0060'; opacity: 0.5; color: var(--accent-hover); font-weight: 400;
}
/* п.8: multi-line code block — an engraved stone tablet: full thin frame + an inset
   second rule (the gap matches the slab fill, so it reads as a carved double border),
   sharp corners. Distinct from the quote's single left rail. Newlines kept, long lines
   wrap (no horizontal scroll in the narrow note pane). */
.grim-body pre, .grim-body--ro pre {
    font-family: var(--font-mono); font-size: 13px; line-height: 1.55;
    white-space: pre-wrap; word-break: break-word; tab-size: 2;
    margin: 14px 0; padding: 14px 17px;
    background: #0b0420; color: var(--accent-hover);
    border: 1px solid rgba(150, 80, 240, 0.45); border-radius: 2px;
    box-shadow: inset 0 0 0 3px #0b0420, inset 0 0 0 4px rgba(120, 50, 210, 0.30),
                0 0 14px rgba(80, 20, 180, 0.12);
}
.grim-body hr, .grim-body--ro hr {
    border: none; height: 14px; margin: 14px 0; background-repeat: no-repeat; background-position: center;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12'%3E%3Cline x1='0' y1='6' x2='80' y2='6' stroke='rgba(130,50,220,0.35)' stroke-width='0.8'/%3E%3Cpath d='M96 6 L100 2 L104 6 L100 10 Z' fill='rgba(160,90,255,0.55)'/%3E%3Cline x1='120' y1='6' x2='200' y2='6' stroke='rgba(130,50,220,0.35)' stroke-width='0.8'/%3E%3C/svg%3E");
}

/* ── п.16: каллауты (врезки) ──────────────────────────────────────────────────
   <div class="grim-co grim-co-TYPE"><div class="grim-co-body">…</div></div>.
   The gothic glyph is painted by CSS only (::before mask) — никакого SVG в теле
   заметки. Иконка центрируется по ПЕРВОЙ строке (flex align-items:flex-start +
   ::before высотой в строку, маска по центру) — для многострочных не съезжает. */
.grim-body .grim-co, .grim-body--ro .grim-co {
    --co-c:   var(--accent);
    --co-bd:  var(--border-mid);
    --co-ico: none;
    display: flex; align-items: flex-start; gap: 11px;
    margin: 16px 0; padding: 12px 15px 12px 14px;
    border-radius: var(--radius-md);
    background: linear-gradient(100deg, color-mix(in srgb, var(--co-c) 9%, var(--bg-input)), var(--bg-input) 72%);
    border: 1px solid var(--co-bd); border-left: 3px solid var(--co-c);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.012), 0 0 16px -7px var(--co-c);
}
.grim-body .grim-co::before, .grim-body--ro .grim-co::before {
    content: ''; flex: 0 0 21px; height: 1.62em;
    background: var(--co-c);
    -webkit-mask: var(--co-ico) center / 21px 21px no-repeat;
            mask: var(--co-ico) center / 21px 21px no-repeat;
    filter: drop-shadow(0 0 4px color-mix(in srgb, var(--co-c) 50%, transparent));
}
.grim-body .grim-co-body, .grim-body--ro .grim-co-body {
    flex: 1 1 auto; min-width: 0;
    /* body text takes the callout's hue (slightly lifted toward white for legibility) */
    color: color-mix(in srgb, var(--co-c) 82%, var(--text-primary));
}
.grim-co-body > :first-child { margin-top: 0; }
.grim-co-body > :last-child  { margin-bottom: 0; }

/* type rules carry the `.grim-body`/`.grim-body--ro` prefix so their specificity
   matches the base `.grim-body .grim-co` rule and wins by source order — otherwise
   the base `--co-c`/`--co-ico` defaults (2-class) would override a bare `.grim-co-*`. */
.grim-body .grim-co-info, .grim-body--ro .grim-co-info {
    --co-c: var(--accent); --co-bd: var(--border-mid);
    --co-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.2' opacity='.55'/%3E%3Ccircle cx='12' cy='12' r='6.6'/%3E%3Cpath d='M12 4.6V8M12 16V19.4M4.6 12H8M16 12H19.4' opacity='.7'/%3E%3Cpath d='M12 7.2 13.4 10.6 16.8 12 13.4 13.4 12 16.8 10.6 13.4 7.2 12 10.6 10.6Z' fill='%23000' stroke='none' fill-opacity='.5'/%3E%3Ccircle cx='12' cy='12' r='1.5' fill='%23000' stroke='none'/%3E%3C/svg%3E");
}
.grim-body .grim-co-warn, .grim-body--ro .grim-co-warn {
    --co-c: #e03060; --co-bd: rgba(220, 30, 70, 0.42);
    --co-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 11.4C5 6.9 8.1 3.7 12 3.7C15.9 3.7 19 6.9 19 11.4C19 13.6 18.1 15.1 17 16.1V18.4C17 19.2 16.4 19.6 15.7 19.6H8.3C7.6 19.6 7 19.2 7 18.4V16.1C5.9 15.1 5 13.6 5 11.4Z'/%3E%3Ccircle cx='9' cy='11.4' r='1.9'/%3E%3Ccircle cx='15' cy='11.4' r='1.9'/%3E%3Cpath d='M12 13.4 11 15.6H13Z' fill='%23000' stroke='none'/%3E%3Cpath d='M9.2 19.6V17.6M12 19.6V17.4M14.8 19.6V17.6' opacity='.75'/%3E%3C/svg%3E");
}
.grim-body .grim-co-secret, .grim-body--ro .grim-co-secret {
    --co-c: #9a86c8; --co-bd: rgba(120, 100, 170, 0.42);
    --co-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.6 12C5 8.4 8.3 6.6 12 6.6C15.7 6.6 19 8.4 21.4 12C19 15.6 15.7 17.4 12 17.4C8.3 17.4 5 15.6 2.6 12Z'/%3E%3Ccircle cx='12' cy='12' r='3.3'/%3E%3Ccircle cx='12' cy='12' r='1.3' fill='%23000' stroke='none'/%3E%3C/svg%3E");
}

/* ── п.16: callout type-picker popover (under the toolbar button) ── */
.grim-co-pop {
    position: fixed; z-index: 1200; padding: 5px;
    display: flex; flex-direction: column; gap: 2px;
    background: var(--bg-input); border: 1px solid var(--border-mid);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 32px -10px #000, 0 0 0 1px var(--accent-glow);
    animation: grimCoPopIn var(--dur-quick) var(--ease-gothic);
}
@keyframes grimCoPopIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
.grim-co-pop-it {
    display: flex; align-items: center; gap: 9px;
    padding: 7px 14px 7px 9px; background: none; border: none; border-radius: 7px;
    cursor: pointer; text-align: left;
    font-family: var(--font-label); letter-spacing: 0.7px; text-transform: uppercase;
    font-size: 13px; color: var(--text-secondary);
    transition: background var(--dur-quick) var(--ease-gothic), color var(--dur-quick) var(--ease-gothic);
}
.grim-co-pop-it:hover { background: var(--accent-soft); }
.grim-co-pop-ic { display: inline-flex; width: 20px; height: 20px; flex: 0 0 20px; }
.grim-co-pop-ic svg { width: 20px; height: 20px; }
/* each option (icon + label) wears its type's hue, lifted toward white like the body */
.grim-co-pop-it.grim-co-info   { color: color-mix(in srgb, var(--accent) 82%, var(--text-primary)); }
.grim-co-pop-it.grim-co-warn   { color: color-mix(in srgb, #e03060 82%, var(--text-primary)); }
.grim-co-pop-it.grim-co-secret { color: color-mix(in srgb, #9a86c8 82%, var(--text-primary)); }
.grim-co-pop-it.grim-co-info   .grim-co-pop-ic { color: var(--accent); }
.grim-co-pop-it.grim-co-warn   .grim-co-pop-ic { color: #e03060; }
.grim-co-pop-it.grim-co-secret .grim-co-pop-ic { color: #9a86c8; }
@media (prefers-reduced-motion: reduce) { .grim-co-pop { animation: none; } }

/* ── format toolbar: floats in on hover/focus ── */
.fmt-bar {
    display: grid; grid-template-rows: 0fr; opacity: 0; margin: 0 18px 0 52px;
    transition: grid-template-rows 0.26s var(--ease-gothic), opacity 0.18s ease, margin-bottom 0.26s var(--ease-gothic);
}
/* AUTO mode (default, no bar-* class): reveal on hover / while editing.
   Chain goes through .grim-page-main (п.14 wrapper) — the bar is its direct child.
   Hover/focus is scoped to the content wrapper so hovering the TOC rail doesn't pop it. */
.grim-page:not(.bar-open):not(.bar-closed) > .grim-page-main:hover > .fmt-bar,
.grim-page:not(.bar-open):not(.bar-closed) > .grim-page-main:focus-within > .fmt-bar,
.grim-page.bar-open > .grim-page-main > .fmt-bar { grid-template-rows: 1fr; opacity: 1; margin-bottom: 8px; }
/* CLOSED mode keeps the base hidden state even on hover/focus (no extra rule needed). */
/* Pure collapse wrapper: no padding/border/bg so the bar folds to a true 0 height
   when hidden (the chrome lives on .fmt-cluster, which the overflow clips away). */
.fmt-inner { min-height: 0; overflow: hidden; }
.fmt-cluster {
    display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 4px 9px;
    background: rgba(6, 2, 20, 0.72); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 8px;
    box-shadow: var(--shadow-sm);
}
.fmt-grp { display: inline-flex; align-items: center; gap: 2px; }
.fmt-btn {
    min-width: 30px; height: 28px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 1px solid transparent; border-radius: 4px; color: var(--text-muted);
    cursor: pointer; transition: all var(--transition);
    font-family: var(--font-label); font-size: 11px; font-weight: 600; letter-spacing: 0.5px;
}
.fmt-btn svg { width: 16px; height: 16px; }
.fmt-btn:hover { color: var(--accent-hover); background: var(--accent-soft); border-color: var(--border-mid); }
.fmt-btn.on {
    color: var(--accent-hover); background: linear-gradient(135deg, rgba(110,30,220,0.30), rgba(80,15,180,0.18));
    border-color: var(--border-mid); box-shadow: inset 0 0 0 1px rgba(150,70,255,0.25);
}
.fmt-btn.export { padding: 0 10px; gap: 6px; color: var(--text-secondary); text-transform: uppercase; font-size: 10px; letter-spacing: 1px; }
.fmt-btn.export:hover { color: var(--accent-hover); }

/* top-bar right actions: ghost export + inscribe */
.grim-bar-acts { display: inline-flex; align-items: center; gap: 8px; }
.grim-ghost-btn {
    display: inline-flex; align-items: center; gap: 6px;
    background: transparent; border: 1px solid var(--border); border-radius: var(--radius-md);
    color: var(--text-muted); cursor: pointer; padding: 9px 13px;
    font-family: var(--font-label); font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
    transition: all var(--transition);
}
.grim-ghost-btn svg { width: 14px; height: 14px; }
.grim-ghost-btn:hover { color: var(--accent-hover); border-color: var(--border-mid); background: var(--accent-soft); }
/* п.6: destructive ghost button («Опустошить склеп») — quiet warm rest state, red on
   hover, and the same armed pulse as the per-note destroy button. */
.grim-ghost-btn.grim-danger-btn { color: rgba(201, 138, 152, 0.85); border-color: rgba(200, 60, 80, 0.30); }
.grim-ghost-btn.grim-danger-btn:hover { color: var(--prio-high); border-color: var(--prio-high-border); background: var(--prio-high-bg); }
.grim-ghost-btn.grim-danger-btn.confirm-armed {
    color: var(--prio-high); border-color: rgba(230, 60, 80, 0.8);
    background: rgba(200, 30, 50, 0.22);
    animation: dangerPulse 0.5s ease infinite alternate;
}

.grim-meta {
    display: flex; flex-direction: column; align-items: center; gap: 11px;
    /* equal left/right inset so the chip row and button row sit symmetrically. */
    padding: 10px 16px 12px 16px;
    border-top: 1px solid var(--border);
    margin: 8px 16px 0 16px;
}
/* Timestamps as little wax-seal chips, stacked above the action row so they never
   compete with the buttons for width (the old single-row date clipped to «СЕГОДН…»
   once a third action button was added). «правлено» = last edit, «начертано» = born. */
.grim-stamps { display: flex; flex-wrap: wrap; gap: 8px; }
/* Chips mirror the action buttons' geometry (same padding/radius/font/glyph size) so the
   two footer rows read as one symmetric block — they're just non-interactive (no hover,
   no cursor). Text matches the buttons' brightness; «начертано» stays the quieter sibling. */
.grim-stamp {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--bg-item); white-space: nowrap;
    font-family: var(--font-label); font-size: 10.5px; letter-spacing: 1px;
    text-transform: uppercase; color: var(--text-secondary);
}
.grim-stamp svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--accent-hover); }
.grim-stamp.is-created { color: var(--text-muted); }   /* birth date reads quieter than the live edit */
.grim-stamp.is-created svg { color: var(--text-muted); opacity: 0.8; }
/* Date = quiet metadata: borderless, flexible, truncates so the buttons stay one row. */
.grim-date {
    display: flex; align-items: center; gap: 6px;
    flex: 1 1 0; min-width: 0;   /* basis 0 → never forces a wrap; shrinks via ellipsis */
    font-family: var(--font-label); font-size: 10px; letter-spacing: 1px;
    text-transform: uppercase; color: var(--text-muted); opacity: 0.8;
}
.grim-date svg { width: 13px; height: 13px; flex-shrink: 0; }
.grim-date span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Actions = real buttons: visible rest state (border + bg), icon + label. */
.grim-acts { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px; flex-shrink: 0; }
.grim-act {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    background: var(--bg-item); border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--text-secondary); cursor: pointer; padding: 6px 12px;
    font-family: var(--font-label); font-size: 10.5px; letter-spacing: 1px; text-transform: uppercase;
    transition: all var(--transition);
}
.grim-act svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-muted); transition: color var(--transition); }
.grim-act:hover { color: var(--text-primary); border-color: var(--border-bright); background: var(--accent-soft); box-shadow: 0 0 12px rgba(120, 40, 220, 0.18); }
.grim-act:hover svg { color: var(--accent-hover); }
/* Pin toggle lit when the record is pinned (mirrors .btn-pin.active on tasks). */
.grim-act.is-pin.active { color: rgba(205, 140, 255, 0.98); border-color: var(--border-bright); background: var(--accent-soft); box-shadow: 0 0 12px rgba(120, 40, 220, 0.18); }
.grim-act.is-pin.active svg { color: var(--accent-hover); }
.grim-act.danger:hover { color: var(--prio-high); border-color: var(--prio-high-border); background: var(--prio-high-bg); box-shadow: none; }
.grim-act.danger:hover svg { color: var(--prio-high); }
/* Armed (awaiting the confirming 2nd click): red wash + pulsing glow + red glyph. */
.grim-act.danger.confirm-armed {
    color: var(--prio-high); border-color: rgba(230, 60, 80, 0.8);
    background: rgba(200, 30, 50, 0.22);
    animation: dangerPulse 0.5s ease infinite alternate;
}
.grim-act.danger.confirm-armed svg { color: var(--prio-high); }

/* ── п.9 note colour — variant C (glow) ──────────────────────────────────────
   --nc = raw picked colour (soft halo only); --nc-ink = JS lightness-clamped,
   contrast-safe version that drives anything that must READ on the dark page. */

/* List leaf has overflow:hidden → the glow must be INSET (an outer shadow would be
   clipped). Border tint + inset halo + ink-tinted bar + ink-tinted title. */
.grim-leaf.has-color {
    border-color: color-mix(in srgb, var(--nc-ink) 36%, var(--border));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nc-ink) 22%, transparent),
                inset 0 0 12px color-mix(in srgb, var(--nc) 15%, transparent);
}
.grim-leaf.has-color::before {
    background: linear-gradient(180deg, var(--nc-ink), color-mix(in srgb, var(--nc) 45%, transparent));
    box-shadow: 0 0 8px color-mix(in srgb, var(--nc) 50%, transparent);
}
/* Colour the WHOLE list entry — title, snippet body, date, glyphs — but keep the
   ORIGINAL brightness hierarchy: tint each with the same ink at the relative
   strength it had (title brightest → snippet → date dimmest; the date glyph stays
   a touch brighter than its label, as --accent-hover was vs --text-muted). The
   date element's own opacity:0.72 still applies, so it lands below the snippet. */
.grim-leaf.has-color .grim-leaf-t { color: var(--nc-ink); text-shadow: 0 0 9px color-mix(in srgb, var(--nc) 32%, transparent); }
.grim-leaf.has-color .grim-leaf-s { color: color-mix(in srgb, var(--nc-ink) 64%, transparent); }
.grim-leaf.has-color .grim-leaf-d { color: color-mix(in srgb, var(--nc-ink) 70%, transparent); }
.grim-leaf.has-color .grim-leaf-d svg { color: var(--nc-ink); }
.grim-leaf.has-color .grim-snip-ic { color: var(--nc-ink); }   /* body structure glyphs, brighter than snippet text — as --accent-hover was */
.grim-leaf.has-color .grim-leaf-fold svg { color: var(--nc-ink); }
.grim-leaf.has-color:hover::before { background: linear-gradient(180deg, var(--nc-ink), color-mix(in srgb, var(--nc) 55%, transparent)); box-shadow: 0 0 10px color-mix(in srgb, var(--nc) 60%, transparent); }
/* active wash still owns the bg; keep the colour bar + inset halo on top of it */
.grim-leaf.has-color.active {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nc-ink) 28%, transparent),
                inset 0 0 14px color-mix(in srgb, var(--nc) 14%, transparent);
}

/* Detail page stays ENTIRELY original (per request): title default heading colour,
   divider/fleur original violet. The note's colour lives in the list + the «цвет»
   button only — the open page is a neutral reading surface. */

/* Colour act button: crystal fills with the note's ink when a colour is set. */
.grim-act.is-color.active { color: var(--nc-ink); border-color: color-mix(in srgb, var(--nc-ink) 50%, var(--border)); }
.grim-act.is-color.active svg { color: var(--nc-ink); }
.grim-act.is-color.active svg path { fill: color-mix(in srgb, var(--nc) 40%, transparent); }

/* mobile "back to list" — hidden on desktop (both panes visible) */
.grim-back {
    display: none;
    position: absolute;
    top: 6px; right: 12px;
    width: 30px; height: 30px;
    border-radius: 50%; border: 1px solid var(--border);
    background: var(--bg-item); color: var(--text-secondary);
    align-items: center; justify-content: center; cursor: pointer; transition: all var(--transition);
    z-index: 2;
}
.grim-back svg { width: 14px; height: 16px; transform: rotate(-90deg); }
.grim-back:hover { border-color: var(--border-bright); color: var(--accent-hover); }

/* ── empty grimoire / crypt ── */
.grim-empty {
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 64px 20px;
}
.grim-empty-ic svg { width: 60px; height: 60px; color: var(--accent); opacity: 0.5; filter: drop-shadow(0 0 12px var(--accent-glow)); }
.grim-empty p { font-family: var(--font-title); font-size: 19px; letter-spacing: 1.5px; color: var(--text-secondary); margin-top: 4px; }
.grim-empty-sub { font-size: 14px; font-style: italic; color: var(--text-muted); opacity: 0.85; }
.grim-empty-btn { margin-top: 10px; }

@media (prefers-reduced-motion: reduce) {
    .grim-leaf.gl-in, .grim-page, .grim-leaf-spike { animation: none; }
    .fmt-bar { transition: opacity 0.12s linear; }
}

@media (max-width: 640px) {
    .grim-bar { flex-wrap: wrap; }
    .grim-layout { flex-direction: column; gap: 0; }
    .grim-list, .grim-detail { flex: none; width: 100%; }
    .grim-detail { display: none; padding-left: 0; border-left: none; }
    .grim-layout.show-detail .grim-list { display: none; }
    .grim-layout.show-detail .grim-detail { display: block; }
    .grim-back { display: flex; }
    .grim-title-in, .grim-title-ro { padding-right: 42px; }
    /* footer: stack date over the action buttons (no cramped single row) */
    .grim-date { flex: 0 0 100%; }
    .grim-acts { width: 100%; justify-content: center; }
    .grim-stamps { justify-content: center; }
}

/* ============================================================
   Sync Phase 3 — reptilian-eye status glyph + panel + quarantine
   ============================================================ */
/* Floating sentinel — bottom-LEFT, mirroring the pen-sound «Сосуд» FAB at the
   bottom-right (same circular chrome: bg / hairline border / blur / soft shadow).
   The eye keeps watch over the page; clicking opens the sync panel. The CHROME
   stays at full opacity so the control is always readable over content; only the
   EYE's stroke colour + opacity reflect the sync state (so "offline/asleep" dims
   the eye inside a still-visible ring rather than fading the whole button out). */
.sync-glyph {
    position: fixed; bottom: 22px; left: 22px; z-index: 50;
    width: 46px; height: 46px; padding: 5px;          /* 46 − 2×5 ⇒ a 36px eye */
    border-radius: 50%;
    background: var(--bg-app);
    border: 1px solid var(--border-mid);
    color: var(--text-muted);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color var(--dur-quick) var(--ease-gothic),
                border-color var(--dur-quick) var(--ease-gothic),
                box-shadow var(--dur-quick) var(--ease-gothic);
    -webkit-tap-highlight-color: transparent;
}
.sync-glyph:hover { border-color: rgba(140, 60, 255, 0.55); box-shadow: var(--shadow-glow); }
.sync-glyph:hover svg { opacity: 1; }
.sync-glyph svg { width: 100%; height: 100%; display: block; overflow: visible; opacity: .72;
    filter: drop-shadow(0 0 .5px currentColor);                /* faint bloom softens edges */
    transition: opacity var(--dur-quick) var(--ease-gothic); }
.sync-glyph .lids, .sync-glyph .ball, .sync-glyph .brow, .sync-glyph .pupil {
    transform-box: view-box; transform-origin: 12px 12px;
    transition: transform .42s var(--ease-gothic); }
.sync-glyph .lid-up { transition: transform .42s var(--ease-gothic); }
.sync-glyph .iris, .sync-glyph .iris-stria, .sync-glyph .pupil, .sync-glyph .glint, .sync-glyph .tear { transition: opacity .4s; }
.sync-glyph .glint { opacity: 0; }

/* states — the eye mimics sync status (brow follows the upper lid per state) */
/* per-state OPACITY rides on the inner <svg> (not the button) so the floating
   chrome ring never fades — only the eye itself dims/brightens with the state. */
.sync-glyph[data-sync="rest"] svg { opacity: .62; }
.sync-glyph[data-sync="rest"] .lids, .sync-glyph[data-sync="rest"] .ball, .sync-glyph[data-sync="rest"] .brow { transform: scaleY(.9); }

.sync-glyph[data-sync="ok"] { color: #9b86d6; }
.sync-glyph[data-sync="ok"] svg { opacity: .85; }
.sync-glyph[data-sync="ok"] .lids, .sync-glyph[data-sync="ok"] .ball, .sync-glyph[data-sync="ok"] .brow { transform: scaleY(.82); }
.sync-glyph[data-sync="ok"] .lid-up { transform: translateY(1.1px); }

.sync-glyph[data-sync="syncing"] { color: var(--accent-hover); }
.sync-glyph[data-sync="syncing"] svg { opacity: 1; filter: drop-shadow(0 0 2px var(--accent-glow)); }
.sync-glyph[data-sync="syncing"] .glint { opacity: .9; }

.sync-glyph[data-sync="pending"] { color: var(--accent); }
.sync-glyph[data-sync="pending"] svg { opacity: .92; }
.sync-glyph[data-sync="pending"] .glint { opacity: .85; }
.sync-glyph[data-sync="pending"] .lids, .sync-glyph[data-sync="pending"] .ball, .sync-glyph[data-sync="pending"] .brow { transform: scaleY(.92); }

.sync-glyph[data-sync="error"] { color: var(--prio-high); }
.sync-glyph[data-sync="error"] svg { opacity: 1; filter: drop-shadow(0 0 2px var(--prio-high-border)); }
.sync-glyph[data-sync="error"] .lids, .sync-glyph[data-sync="error"] .ball, .sync-glyph[data-sync="error"] .brow { transform: scaleY(.6); }
.sync-glyph[data-sync="error"] .pupil { transform: scaleX(.4); }

.sync-glyph[data-sync="signed-out"] svg { opacity: .7; }
.sync-glyph[data-sync="signed-out"] .lids, .sync-glyph[data-sync="signed-out"] .ball, .sync-glyph[data-sync="signed-out"] .brow { transform: scaleY(.48); }
.sync-glyph[data-sync="signed-out"] .iris, .sync-glyph[data-sync="signed-out"] .iris-stria, .sync-glyph[data-sync="signed-out"] .pupil { opacity: 0; }
.sync-glyph[data-sync="signed-out"] .glint { opacity: .9; }

.sync-glyph[data-sync="offline"] svg { opacity: .42; }
.sync-glyph[data-sync="offline"] .lids, .sync-glyph[data-sync="offline"] .ball, .sync-glyph[data-sync="offline"] .brow { transform: scaleY(.44); }
.sync-glyph[data-sync="offline"] .iris, .sync-glyph[data-sync="offline"] .iris-stria, .sync-glyph[data-sync="offline"] .pupil, .sync-glyph[data-sync="offline"] .glint { opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
    .sync-glyph[data-sync="syncing"] .pupil { animation: syncEyeScan 1.5s ease-in-out infinite; }
    .sync-glyph[data-sync="syncing"] .ball, .sync-glyph[data-sync="syncing"] .lids { animation: syncEyeBlink 3s ease-in-out infinite; }
    .sync-glyph[data-sync="syncing"] .tear { animation: syncEyeNictit 3s ease-in-out infinite; }
}
@keyframes syncEyeScan   { 0%,100% { transform: scaleX(1) scaleY(1); } 48% { transform: scaleX(1.85) scaleY(.82); } }
@keyframes syncEyeBlink  { 0%,40%,54%,100% { transform: scaleY(1); } 47% { transform: scaleY(.08); } }
@keyframes syncEyeNictit { 0%,60%,100% { opacity: 0; } 30% { opacity: .5; } }

/* unresolved-conflict badge on the glyph */
.sync-badge {
    position: absolute; top: -3px; right: -4px; min-width: 14px; height: 14px; padding: 0 3px;
    border-radius: 7px; background: var(--accent); color: #0a0414; font-size: 9px; font-weight: 700;
    line-height: 14px; text-align: center; box-shadow: 0 0 0 2px var(--bg-app); pointer-events: none;
}

/* sync panel (reuses the .snooze-menu float-menu chrome) */
.snooze-menu.sync-panel { min-width: 224px; }
.sync-panel .sync-panel-status { display: flex; align-items: center; gap: 8px; padding: 8px 11px 9px;
    font-size: 12.5px; color: var(--text-secondary); border-bottom: 1px solid var(--border); margin-bottom: 3px; }
.sync-panel .sync-panel-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); flex: 0 0 auto; }
.sync-panel .sync-panel-err { padding: 6px 11px 8px; font-size: 11px; line-height: 1.4; color: var(--prio-high);
    word-break: break-word; border-bottom: 1px solid var(--border); margin-bottom: 3px; opacity: .85; }
.sync-panel .sync-panel-log { border-top: 1px solid var(--border); margin-top: 3px; }
.sync-panel .sync-panel-log summary { padding: 7px 11px; font-size: 11.5px; color: var(--text-muted); cursor: pointer;
    list-style: none; user-select: none; }
.sync-panel .sync-panel-log summary::-webkit-details-marker { display: none; }
.sync-panel .sync-panel-log summary::before { content: '☰ '; opacity: .6; }
.sync-panel .sync-log-list { padding: 0 11px 8px; }   /* the panel itself scrolls (max-height in _openFloatMenu) */
.sync-panel .sync-log-row { font-size: 10.5px; line-height: 1.5; color: var(--text-secondary);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; word-break: break-word; }
.sync-panel .sync-log-t { color: var(--text-muted); opacity: .7; margin-right: 6px; }
.sync-panel-status[data-sync="syncing"] .sync-panel-dot { background: var(--accent-hover); animation: dangerPulse 1.4s ease-in-out infinite; }
.sync-panel-status[data-sync="ok"] .sync-panel-dot { background: #9b86d6; }
.sync-panel-status[data-sync="error"] .sync-panel-dot { background: var(--prio-high); }
.sync-panel-status[data-sync="pending"] .sync-panel-dot { background: var(--accent); }
.sync-panel .sync-panel-quar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sync-panel .sync-panel-quar-n { background: var(--accent); color: #0a0414; font-size: 10px; font-weight: 700;
    min-width: 16px; height: 16px; line-height: 16px; text-align: center; border-radius: 8px; padding: 0 4px; }

/* quarantine review overlay (reuses .modal-overlay/.modal) */
.sync-quar-modal { max-width: 460px; width: 92vw; }
.sync-quar-desc { font-size: 12px; color: var(--text-muted); margin: 4px 0 14px; line-height: 1.5; }
.sync-quar-list { display: flex; flex-direction: column; gap: 8px; max-height: 52vh; overflow: auto; }
.sync-quar-row { display: flex; gap: 10px; align-items: flex-start; justify-content: space-between;
    padding: 10px 11px; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg-item); }
.sync-quar-what { font-size: 12.5px; color: var(--text-secondary); margin-bottom: 4px; }
.sync-quar-loser { font-size: 12px; color: var(--text-muted); word-break: break-word; line-height: 1.4; }
.sync-quar-loser i { color: var(--text-muted); opacity: .7; }
.sync-quar-acts { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.sync-quar-restore, .sync-quar-dismiss { font-size: 11.5px; padding: 5px 10px; border-radius: var(--radius-sm);
    cursor: pointer; border: 1px solid var(--border-mid); background: var(--accent-soft); color: var(--text-primary);
    white-space: nowrap; transition: background var(--dur-micro), border-color var(--dur-micro), color var(--dur-micro); }
.sync-quar-restore:hover { border-color: var(--border-bright); background: var(--accent-dim); color: var(--text-primary); }
.sync-quar-dismiss { background: transparent; color: var(--text-muted); }
.sync-quar-dismiss:hover { color: var(--prio-high); border-color: var(--prio-high-border); }
.sync-quar-empty { color: var(--text-muted); font-size: 12.5px; padding: 16px; text-align: center; }

@media (max-width: 560px) {
    .sync-glyph { bottom: 18px; left: 16px; width: 46px; height: 46px; }
}

