/* Habits — single-pane habit grid: each habit is a row, the last N days
   form a tappable column strip on the right. Visual language is matched
   verbatim to Done's so the suite reads as one family. */

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

/* ── Layout ─────────────────────────────────────────────────────────────
   padding-top compensates for the fixed .appHeader (see header.css) so
   content sits below it instead of behind it. */
.appLayout {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-top: var(--header-height);
    background: var(--bg);
}

.habitsPage {
    width: 100%;
    max-width: 980px;
    margin: 0 auto;
    /* Bottom padding clears the fixed .appFooter (~52px tall) plus a
       comfortable buffer so the last habit row never sits hard against
       the footer top edge. Keep the buffer in sync with the footer's
       height + padding below. */
    padding: 28px 24px 120px;
}

.habitsPageHeader {
    margin-bottom: 24px;
}
.habitsPageEyebrow {
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--mint);
    margin-bottom: 8px;
}
.habitsPageTitle {
    font-size: 28px;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--text);
}
.habitsPageSub {
    margin-top: 6px;
    font-size: 14px;
    color: var(--text-secondary);
}

/* ── Empty state ──────────────────────────────────────────────────────── */
.habitsEmpty {
    margin: 56px 0 32px;
    padding: 40px 24px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
    text-align: center;
    color: var(--text-secondary);
}
.habitsEmptyTitle {
    font-size: 17px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 6px;
}
.habitsEmptySub { font-size: 14px; }

/* ── Grid card ───────────────────────────────────────────────────────────
   The grid is one card. Header row with day labels (mon/tue/...) sits
   at the top; each habit is a row underneath. Rows align via CSS grid
   with a left-side flexible name column and N fixed-width day cells. */
/* --day-cell is set dynamically on :root by applyViewRangeStyles()
   in index.php so a single declaration drives every cell. Putting
   the default here on :root (not .habitGrid) means the JS override
   inherits down into the grid without being shadowed by a more
   specific local declaration. */
:root {
    --day-cell: 28px;
    /* Wide enough for an "icon + Today" pill matching the .habitAddBtn
       size — narrower buttons looked dwarfed by the longer Add CTA. */
    --habit-today-col: 92px;
}
.habitGrid {
    --day-gap: 4px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.habitGridHeader,
.habitRow {
    /* Two-row layout per habit:
         row 1: [label / chips / kebab / streak] [today button]
         row 2: [strip or commit-grid spanning both columns]
       Splitting the cells off into their own band means a row's
       metadata never competes with the cells for horizontal space,
       and every habit's cells start at the same left edge of the
       card regardless of how busy the label is. */
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--habit-today-col);
    grid-template-areas:
        "label today"
        "strip strip";
    column-gap: 12px;
    row-gap: 10px;
    padding: 12px 14px;
    align-items: center;
}
.habitGridHeaderLabel,
.habitRowLabel {
    grid-area: label;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}
.habitGridHeaderRange,
.habitDays {
    grid-area: strip;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    /* Hide the scrollbar — the heatmap fits in the card on typical
       desktop widths, and on narrow screens the user can still
       horizontal-swipe / drag without a visible bar competing for
       attention with the cells. */
    scrollbar-width: none;
}
.habitGridHeaderRange::-webkit-scrollbar,
.habitDays::-webkit-scrollbar { display: none; }
.habitGridHeaderToday,
.habitTodayCell {
    grid-area: today;
}
.habitGridHeaderToday {
    text-align: center;
    color: var(--mint);
    font-weight: 700;
    font-size: 10.5px;
}
.habitGridHeader {
    background: var(--bg-sidebar);
    border-bottom: 1px solid var(--border);
    color: var(--text-tertiary);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 600;
    user-select: none;
}
.habitGridHeaderLabel { padding-left: 4px; }
.habitGridHeaderRange {
    display: flex;
    gap: var(--day-gap);
}
.habitGridHeaderDay {
    width: var(--day-cell);
    flex-shrink: 0;
    text-align: center;
    font-size: 10.5px;
    color: var(--text-tertiary);
    line-height: 1;
}
.habitGridHeaderDay--today {
    color: var(--mint);
    font-weight: 700;
}
.habitGridHeaderDayDate {
    display: block;
    font-size: 9.5px;
    color: var(--text-tertiary);
    margin-top: 2px;
    font-weight: 500;
    letter-spacing: 0;
}

/* Compact header column — used in 3mo/6mo/1y where the per-day day-of-week
   label doesn't fit. Cells stay anchored; the first-of-month marker
   visually divides the strip into months. */
.habitGridHeaderDay--compact {
    font-size: 9px;
    line-height: 1;
}
.habitGridHeaderMonth {
    display: block;
    color: var(--text-secondary);
    font-weight: 600;
    white-space: nowrap;
}

.habitRow {
    border-bottom: 1px solid var(--border);
    transition: background var(--transition);
}
.habitRow:last-child { border-bottom: 0; }

.habitRow.dragging { opacity: 0.4; }
.habitRow.dropAbove { box-shadow: inset 0 2px 0 var(--mint); }
.habitRow.dropBelow { box-shadow: inset 0 -2px 0 var(--mint); }

.habitRowLabel {
    display: flex;
    /* Top-align so the drag handle + colour dot sit next to the
       FIRST line of a wrapped habit name instead of floating in
       the middle of a multi-line block. The handle/dot then offset
       themselves down to the line's vertical centre — see below. */
    align-items: flex-start;
    gap: 10px;
    min-width: 0;
}

/* Both the drag grip and the colour dot sit in a "cell" the height
   of one .habitName line (font-size × line-height) so flex centring
   inside that cell parks them on the middle of the first wrapped
   line. The cell is offset by the textarea's top padding so the
   maths still works once the user starts typing. */
.habitDragHandle,
.habitColorDot {
    align-self: flex-start;
    margin-top: 4px;                    /* matches .habitName padding-top */
    min-height: calc(14.5px * 1.35);    /* matches .habitName first line */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.habitDragHandle {
    color: var(--text-tertiary);
    font-size: 12px;
    cursor: grab;
    width: 14px;
    flex-shrink: 0;
    opacity: 0;
    transition: opacity var(--transition);
}
.habitRow:hover .habitDragHandle { opacity: 0.7; }
.habitDragHandle:active { cursor: grabbing; }

/* The button itself is the centring cell; the visible disc is the
   ::before so the colour swatch keeps its 10px circle even though
   the button stretches to one line-height tall. */
.habitColorDot {
    width: 14px;
    flex-shrink: 0;
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
}
.habitColorDot::before {
    content: '';
    /* Bumped from 10 → 13px so the swatch carries more visual weight
       at typical reading distance — the previous size read as a faded
       bullet point next to the habit name. Outer ring deepened too:
       the bg-coloured separator is now wrapped in a 1px tertiary-text
       outline so the swatch keeps a hard edge against either a white
       page or a hovered row. */
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--habit-color, var(--text-tertiary));
    box-shadow: 0 0 0 2px var(--bg),
                0 0 0 3px var(--text-tertiary);
    transition: transform 120ms ease;
}
.habitColorDot:hover::before {
    transform: scale(1.15);
}

/* Multi-line textarea. Auto-grows to fit content via the JS
   handler; CSS just needs to allow wrapping and disable the
   resize grip + horizontal scroll. */
.habitName {
    flex: 1;
    min-width: 0;
    font-family: inherit;
    font-size: 14.5px;
    font-weight: 500;
    line-height: 1.35;
    color: var(--text);
    background: transparent;
    border: 0;
    outline: none;
    padding: 4px 6px;
    border-radius: 4px;
    transition: background var(--transition);
    resize: none;
    overflow: hidden;
    word-break: break-word;
    white-space: pre-wrap;
}
.habitName:focus { background: var(--bg-sidebar); }
.habitName::-webkit-scrollbar { display: none; }

.habitMeta {
    margin-top: 2px;
    display: inline-flex;
    align-items: center;
    font-family: monospace;
    gap: 4px;
    font-size: 12px;
    color: var(--text-tertiary);
    font-weight: 500;
    flex-shrink: 0;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bg-sidebar);
}
.habitMeta i { font-size: 10px; }
.habitMeta--hot { color: var(--mint); }

/* Per-row kebab. Lives left of the streak chip — destructive actions
   open inside a popover instead of sitting bare on the row. Hidden at
   rest on desktop (fades in on row hover) so the row stays calm; on
   mobile the mobile media query keeps it always visible since hover
   isn't a thing. */
.habitMenuBtn {
    margin-top: 2px;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    border-radius: 4px;
    flex-shrink: 0;
    opacity: 0;
    transition: opacity var(--transition), background var(--transition), color var(--transition);
    cursor: pointer;
    font-size: 13px;
}
.habitRow:hover .habitMenuBtn,
.habitMenuBtn[aria-expanded="true"] { opacity: 1; }
.habitMenuBtn:hover { color: var(--text); background: var(--bg-hover); }
.habitMenuBtn:focus-visible {
    outline: 2px solid var(--mint);
    outline-offset: 2px;
    opacity: 1;
}

.habitMenu {
    position: fixed;
    z-index: 200;
    padding: 4px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
    display: none;
}
.habitMenu[data-open="true"] { display: block; }

.habitMenuItem {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 0;
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.habitMenuItem:hover { background: var(--bg-hover); }
.habitMenuItem:focus-visible {
    outline: 2px solid var(--mint);
    outline-offset: -2px;
}
.habitMenuItem--danger { color: #c33; }
.habitMenuItem--danger:hover {
    background: rgba(195, 51, 51, 0.08);
    color: #c33;
}
.habitMenuItemIcon {
    width: 14px;
    text-align: center;
    font-size: 12px;
    color: inherit;
    flex-shrink: 0;
}

/* Default flex display is used by .habitDays--strip; .habitDays--grid
   overrides this to a CSS grid (7 rows × N week columns) below. */
.habitDays {
    display: flex;
    gap: var(--day-gap);
}

/* ── Grid (heatmap) mode ──────────────────────────────────────────────
   GitHub commit-grid layout for every view longer than 7d. 7 rows are
   Sun..Sat; columns are weeks. Cells set explicit grid-row +
   grid-column inline so slots before the oldest visible day / after
   today simply render as empty cells. The total-weeks count is passed
   in via a CSS custom property so the header markers above stay in
   step with the rows below. */
.habitDays--grid {
    display: grid;
    grid-template-rows: repeat(7, var(--day-cell));
    grid-auto-columns: var(--day-cell);
    grid-auto-flow: column;
    /* Tighten the gap a touch in heatmap mode — GitHub-style grids
       sit ~3px apart and the closer packing makes the year easier to
       read as one cohesive surface. */
    gap: 3px;
}

/* Heatmap cells are styled like GitHub contribution squares: small
   square fills with no outline, just a touch of corner rounding. The
   base .habitDayCell rule's border is dropped here so the surface
   reads as a clean palette of color blocks. */
.habitDays--grid .habitDayCell {
    border-radius: 3px;
    border-width: 0;
    /* Faint inner outline so the empty square keeps a visible edge
       against the card background without competing with the filled
       cells' habit color. */
    box-shadow: inset 0 0 0 1px var(--border);
}
.habitDays--grid .habitDayCell.checked {
    box-shadow: none;
}
.habitDays--grid .habitDayCell--today {
    /* In-grid today marker uses a tight inset mint ring so it still
       reads after the border was dropped above. */
    box-shadow: inset 0 0 0 1.5px var(--mint);
}

.habitGridHeaderRange--grid {
    display: grid;
    grid-template-columns: repeat(var(--total-weeks, 1), var(--day-cell));
    grid-auto-rows: auto;
    gap: var(--day-gap);
    align-items: end;
    padding-bottom: 2px;
}
.habitGridHeaderRange--grid .habitGridHeaderMonth {
    /* Each column slot is exactly --day-cell wide, narrower than any
       month abbreviation, so let the label overflow to the right
       (the next column's label is usually empty). White-space:nowrap
       keeps the abbreviation on one line. */
    font-size: 10px;
    color: var(--text-secondary);
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    overflow: visible;
    text-align: left;
}

/* Day cell: a square. Empty = a soft sidebar-toned fill so the cell
   visibly exists on the page (the old transparent-bg cells washed out
   to near-invisible against the card). Filled = themed habit color. */
.habitDayCell {
    width: var(--day-cell);
    height: var(--day-cell);
    flex-shrink: 0;
    border-radius: 6px;
    border: 1px solid var(--border-strong);
    background: var(--bg-sidebar);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
    padding: 0;
    position: relative;
    overflow: hidden;
}

/* ── Strip-mode cell content (7d view) ───────────────────────────────
   Each cell shows its day-letter (M/T/W…) and day-of-month right
   inside, so the header row above doesn't need a separate label
   strip. Labels switch to white when the cell is checked so they stay
   legible over the colored fill. */
.habitDays--strip .habitDayCell {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    color: var(--text-tertiary);
}
.habitDayCellLabel {
    font-size: 9px;
    font-weight: 600;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.habitDayCellDate {
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    color: var(--text-secondary);
}
.habitDays--strip .habitDayCell.checked .habitDayCellLabel,
.habitDays--strip .habitDayCell.checked .habitDayCellDate {
    color: #fff;
}
/* In strip mode the colored fill + bright labels already say "done"
   — hide the FA checkmark so it doesn't sit on top of the date
   number. Grid mode's tiny cells also drop the glyph; the colored
   fill alone reads as the GitHub-style commit signal. */
.habitDays--strip .habitDayCell.checked::after,
.habitDays--grid  .habitDayCell.checked::after { display: none; }
.habitDayCell:hover {
    border-color: var(--border-strong);
    background: var(--bg-hover);
}
.habitDayCell:active { transform: scale(0.92); }
.habitDayCell:focus-visible {
    outline: 2px solid var(--mint);
    outline-offset: 2px;
}

.habitDayCell.checked {
    background: var(--habit-color, var(--mint));
    border-color: var(--habit-color, var(--mint));
}
.habitDayCell.checked::after {
    content: "\f00c";
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    color: #fff;
    /* Scale the checkmark to the cell so tiny compact-view cells
       (3mo / 6mo / 1y) don't show an oversized glyph crammed into a
       few-pixel box. Caps at 11px for the 28px / 18px ranges. */
    font-size: min(11px, calc(var(--day-cell) * 0.6));
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Today's cell — rings the box in accent so the user can pick out
   "now" in the row at a glance. Applied in both views: strip
   (rightmost square in 1w) and heatmap (current week's cell in 1y).
   The dedicated .habitTodayCell button to the right of the row is
   the always-visible check-off; this in-grid marker is the
   chronological anchor next to the surrounding days. */
.habitDayCell--today {
    box-shadow: inset 0 0 0 1.5px var(--mint);
}
.habitDayCell--future {
    visibility: hidden;          /* keeps grid alignment without showing tappable cells */
    pointer-events: none;
}

/* Skipped cells — used by habit.skipWeekends for Sat/Sun. They occupy
   the grid slot so the row stays aligned with the shared header, but
   they read as not-applicable: subdued, dashed, no hover, no tap. */
.habitDayCell--skipped,
.habitDayCell--skipped:hover {
    background: transparent;
    border-style: dashed;
    border-color: var(--border);
    cursor: default;
    opacity: 0.4;
    pointer-events: none;
}
.habitDayCell--skipped.checked,
.habitDayCell--skipped.checked::after {
    /* If a check-in already exists from before skip-weekends was
       enabled (or before the cadence changed), still hint at it — but
       muted, so the user knows the data is preserved without it
       counting toward today's streak. */
    background: transparent;
    border-color: var(--border);
    color: var(--text-tertiary);
}

/* Off-cadence cells — the habit's frequency (every N days/weeks/…)
   doesn't include this day. Per TODOs.md they should "disappear", so
   visibility:hidden retires the cell completely while preserving the
   grid slot so the row stays aligned with the shared header (which is
   a SUITE-level header — one alignment, many habits). */
.habitDayCell--off-cadence,
.habitDayCell--off-cadence:hover,
.habitDayCell--off-cadence.checked {
    visibility: hidden;
    pointer-events: none;
}

/* ── Distinct "Today" button ──────────────────────────────────────────
   Lives at the right end of every habit row, OUTSIDE the (potentially
   scrolling) day strip. Sized larger than a grid cell + an explicit
   "Today" label so the check-off button for today is always present
   and unmistakable, even at the 1-year view where strip cells are
   only a few pixels wide. */
.habitTodayCell {
    /* Visually identical to .habitAddBtn at the bottom of the grid —
       icon-left + label, same padding / border / radius / colors so
       the row's primary check-off and the grid's primary "add" CTA
       read as one family. Lives in the row's grid `today` column. */
    width: 100%;
    max-width: var(--habit-today-col);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.habitTodayCell:hover {
    color: var(--text);
    background: var(--bg-hover);
    border-color: var(--text-tertiary);
}
.habitTodayCell:focus-visible {
    outline: 2px solid var(--mint);
    outline-offset: 2px;
}
.habitTodayCell .habitTodayCellIcon {
    font-size: 12px;
    opacity: 1;                   /* icon always visible — mirrors .habitAddBtn */
}
.habitTodayCell.checked {
    background: var(--habit-color, var(--mint));
    border-color: var(--habit-color, var(--mint));
    color: #fff;
}
.habitTodayCell.habitTodayCell--skipped,
.habitTodayCell.habitTodayCell--skipped:hover {
    background: var(--bg);
    color: var(--text-tertiary);
    border-color: var(--border);
    cursor: default;
    opacity: 0.5;
}

/* ── View-range selector ──────────────────────────────────────────────
   Segmented pill sitting in the page header. Switches between the six
   ranges defined in JS (VIEW_RANGES); active button gets the accent
   surface. Persists per-browser via localStorage. */
.habitsViewRange {
    margin-top: 14px;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 3px;
    background: var(--bg-sidebar);
    border: 1px solid var(--border);
    border-radius: 999px;
}
.habitsViewBtn {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 500;
    padding: 5px 12px;
    border-radius: 999px;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease;
    letter-spacing: -0.005em;
}
.habitsViewBtn:hover { color: var(--text); }
.habitsViewBtn.is-active {
    background: var(--bg);
    color: var(--text);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.habitsViewBtn:focus-visible {
    outline: 2px solid var(--mint);
    outline-offset: 2px;
}

/* Add-habit row sits inside the same grid card so it visually attaches
   to the list rather than floating below it. */
.habitAddRow {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    border-top: 1px dashed var(--border-strong);
    background: var(--bg-sidebar);
}
.habitAddInput {
    flex: 1;
    border: 0;
    background: transparent;
    font-size: 14.5px;
    color: var(--text);
    padding: 6px 6px;
    outline: none;
}
.habitAddInput::placeholder { color: var(--text-tertiary); }
.habitAddBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.habitAddBtn:hover {
    color: var(--text);
    background: var(--bg-hover);
    border-color: var(--text-tertiary);
}
.habitAddBtn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ── Color picker popover ────────────────────────────────────────────── */
.colorPicker {
    position: fixed;
    z-index: 200;
    display: none;
    grid-template-columns: repeat(4, auto);
    gap: 6px;
    padding: 8px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
}
.colorPicker[data-open="true"] { display: grid; }
.colorPickerSwatch {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 0;
    cursor: pointer;
    background: var(--swatch);
    box-shadow: 0 0 0 2px var(--bg), inset 0 0 0 1px rgba(0, 0, 0, 0.06);
    transition: transform 120ms ease;
}
.colorPickerSwatch:hover { transform: scale(1.1); }
.colorPickerSwatch.active {
    box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--mint);
}

/* ── Primary header button ".notesPaneNewBtn" — matches Done verbatim
   so the New CTA looks identical across tools. ─────────────────────── */
.notesPaneNewBtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-width: 30px;
    min-height: 30px;
    padding: 0 10px;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: var(--bg-sidebar);
    font-size: 15px;
    font-weight: 500;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
    transition: background 120ms ease, color 120ms ease,
                box-shadow 160ms ease, transform 120ms ease;
    flex-shrink: 0;
}
.notesPaneNewBtn:not(:has(.notesPaneNewBtnLabel)) {
    padding: 0;
    width: 30px;
}
.notesPaneNewBtnLabel {
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.005em;
    white-space: nowrap;
}
.notesPaneNewBtn:hover {
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16),
                inset 0 1px 0 rgba(255, 255, 255, 0.12);
    transform: translateY(-0.5px);
}
.notesPaneNewBtn:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* ── Sync status chip — verbatim from Done so the indicator reads the
   same across the suite. ───────────────────────────────────────────── */
.syncStatus {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.005em;
    margin-right: 4px;
    white-space: nowrap;
    transition: color 200ms ease, border-color 200ms ease;
}
.syncStatusIcon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    font-size: 12px;
    line-height: 1;
}
.syncStatus.syncStatus--ok {
    color: #1f6b3d;
    border-color: rgba(45, 122, 74, 0.30);
}
.syncStatus.syncStatus--syncing {
    color: var(--text-secondary);
    border-color: var(--border-strong);
}
.syncStatus.syncStatus--offline {
    color: #a32424;
    border-color: rgba(160, 38, 38, 0.30);
}
.syncStatusLabel { display: inline; }

/* ── Toast (undo) ────────────────────────────────────────────────────── */
.habitsToast {
    position: fixed;
    bottom: 60px;
    right: 20px;
    display: none;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--text);
    color: var(--bg);
    border-radius: var(--radius);
    font-size: 13px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
    z-index: 150;
    max-width: 360px;
}
.habitsToast[data-open="true"] { display: flex; }
.habitsToastMsg { flex: 1; }

/* ── Footer ──────────────────────────────────────────────────────────────
   Pinned to the bottom of the viewport so a long list of habits scrolls
   underneath instead of pushing the footer up between rows. The page's
   bottom padding (.habitsPage) reserves enough room beneath the last
   row to scroll clear of this footer. Background matches the page so
   content shows through cleanly without a visible seam at small sizes;
   z-index sits below .appHeader (z-index 100) so any popover that
   anchors to the header still draws on top. */
.appFooter {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    background: var(--bg);
    border-top: 1px solid var(--border);
    padding: 16px 24px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 12px;
}

/* ── Mobile ─────────────────────────────────────────────────────────────
   Same two-row template as desktop; just tighten padding + typography
   for small screens. The label flex-wraps so chips drop to a second
   line when they don't fit beside the name. */
@media (max-width: 768px) {
    .habitsPage { padding: 18px 14px 120px; }
    .habitsPageTitle { font-size: 22px; }

    .habitGridHeader,
    .habitRow {
        padding: 14px 14px;
        row-gap: 8px;
    }
    .habitGridHeader { padding: 12px 14px 10px; }
    .habitGridHeaderRange,
    .habitDays {
        gap: 6px;
    }

    /* Cells use the same --day-cell variable as desktop so the chosen
       view range carries over; just bump the radius a touch for the
       larger 7d/14d tap targets. */
    .habitDayCell {
        width: var(--day-cell);
        height: var(--day-cell);
        border-radius: 7px;
    }
    .habitDayCell.checked::after { font-size: 13px; }

    /* Habit identity band: dot + name (wraps to multi-line if long) +
       delete pinned to the right. Drag handle and streak chip drop off
       the small viewport — desktop is where ordering and stats live. */
    .habitRowLabel { gap: 10px; }
    .habitName {
        font-size: 15.5px;
        white-space: normal;
        line-height: 1.35;
        padding: 2px 0;
    }
    .habitDragHandle { display: none; }
    /* Streak chip stays VISIBLE on mobile — used to be hidden, but it's
       the row's loudest reward and the kebab now occupies the slot
       previously held by the trash icon. */
    .habitMeta { display: inline-flex; }
    .habitMenuBtn {
        opacity: 1;
        width: 32px; height: 32px;
        font-size: 14px;
    }
    /* Mobile: the centring cell tracks the mobile .habitName line-box
       (15.5px × 1.35) and its tighter 2px top padding. The visible
       disc bumps from 10 → 12 to match the larger touch target. */
    .habitColorDot {
        margin-top: 2px;
        min-height: calc(15.5px * 1.35);
        width: 16px;
    }
    .habitColorDot::before { width: 12px; height: 12px; }

    .syncStatus {
        width: 35px;
        height: 35px;
        padding: 0;
        gap: 0;
        margin-right: 0;
    }
    .syncStatusLabel { display: none; }
}

@media (max-width: 480px) {
    .habitGridHeader,
    .habitRow { padding: 12px 12px; }
    .habitGridHeaderRange,
    .habitDays { gap: 4px; }
}

/* ── Confirm modal scaffold (delete account etc. — used on the account
   page; harmless to define alongside the index app even if unused). */
.confirmModal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 300;
    align-items: center;
    justify-content: center;
}
.confirmModal.open { display: flex; }
.confirmModalBackdrop {
    position: absolute;
    inset: 0;
    background: rgba(20, 20, 20, 0.32);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}
.confirmModalContent {
    position: relative;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.06);
    padding: 22px 22px 18px;
    width: 380px;
    max-width: calc(100% - 32px);
}
.confirmModalBtn {
    padding: 7px 14px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 500;
    transition: background var(--transition), color var(--transition), border-color var(--transition), opacity var(--transition);
    border: 1px solid transparent;
    cursor: pointer;
}
.confirmModalBtnPrimary {
    color: #fff;
    background: var(--accent);
}
.confirmModalBtnCancel {
    background: transparent;
    color: var(--text-secondary);
    border-color: var(--border);
}
.confirmModalBtnCancel:hover { background: var(--bg-hover); color: var(--text); }
.confirmModalBtnDanger {
    color: #fff;
    background: #c33;
}
.confirmModalBtnDanger:hover { background: #b02a2a; }

/* Title / body / actions / skip toggle inside .confirmModalContent —
   matches Noted's deleteNoteModal so the suite confirms destructive
   actions in the same shape across tools. */
.confirmModalTitle {
    font-size: 16px;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: 6px;
    color: var(--text);
}
.confirmModalBody {
    font-size: 13.5px;
    color: var(--text-secondary);
    line-height: 1.5;
    margin-bottom: 16px;
}
.confirmModalBody #deleteHabitName {
    color: var(--text);
    font-weight: 500;
}
.confirmModalCheckbox {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: var(--text-secondary);
    cursor: pointer;
    margin-bottom: 18px;
    user-select: none;
    padding: 6px 0;
}
.confirmModalCheckbox input {
    cursor: pointer;
    accent-color: var(--accent);
    width: 14px;
    height: 14px;
}
.confirmModalCheckbox:hover { color: var(--text); }
.confirmModalActions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* ── Frequency / reminder modal controls ─────────────────────────────────
   Inline form row used inside .confirmModalContent for cadence + time
   selection. Inputs adopt the same border/radius language as the rest
   of the suite so the modals feel native rather than borrowed from the
   browser default form rendering. */
.freqRow {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}
.freqRowLabel {
    font-size: 13.5px;
    color: var(--text-secondary);
    font-weight: 500;
}
.freqInput,
.freqSelect {
    font-family: inherit;
    font-size: 13.5px;
    color: var(--text);
    background: var(--bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    padding: 6px 8px;
    outline: none;
    transition: border-color var(--transition), background var(--transition);
}
.freqInput:focus,
.freqSelect:focus {
    border-color: var(--accent);
    background: var(--bg-sidebar);
}
.freqInput {
    width: 72px;
    text-align: center;
    /* Hide the browser's number spinners — the modal already constrains
       to integer values, and the arrows fight the modal's look. */
    -moz-appearance: textfield;
    appearance: textfield;
}
.freqInput::-webkit-outer-spin-button,
.freqInput::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.freqInput.is-disabled,
.freqInput:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.freqSelect {
    cursor: pointer;
    min-width: 110px;
}
.freqPreview {
    margin: -4px 0 16px;
    font-size: 12.5px;
    color: var(--text-tertiary);
    font-style: italic;
}

.reminderModeRow {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}
.reminderModeRow:last-of-type { margin-bottom: 16px; }
.reminderModeOption {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13.5px;
    color: var(--text);
    cursor: pointer;
    user-select: none;
}
.reminderModeOption input[type="radio"] {
    accent-color: var(--accent);
    cursor: pointer;
    width: 14px;
    height: 14px;
}
.reminderTimeInput {
    width: 130px;
}

/* ── Per-habit metadata chips (frequency / reminder / skip-weekends) ─────
   Visually a button-flavoured .habitMeta — same pill silhouette + size,
   no border, surfaces tertiary text. Only rendered when the habit has
   a non-default value, so the default row stays uncluttered. The
   interactive bits (cursor + hover/focus) are the only differences
   from .habitMeta, which is a non-interactive streak label. */
.habitChip {
    margin-top: 2px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--text-tertiary);
    font-weight: 500;
    flex-shrink: 0;
    padding: 5px 10px;
    border-radius: 999px;
    background: var(--bg-sidebar);
    border: 0;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.habitChip:hover {
    background: var(--bg-hover);
    color: var(--text);
}
.habitChip:focus-visible {
    outline: 2px solid var(--mint);
    outline-offset: 2px;
}
.habitChip i { font-size: 10px; }

@media (max-width: 768px) {
    .freqInput { width: 64px; }
    .freqSelect { min-width: 96px; }
}
