/*
  Demerzel PWA, TOSS (토스) design language.

  This stylesheet implements the locked Toss system from _design/toss-system.md and
  the polished mockup _design/mockup-toss-final.html on the real app. It REPLACES the
  rejected "Quiet Instrument" (warm paper + serif) styling. The Toss spine: one clear
  primary action per screen, big friendly bold typography, generous whitespace,
  reassuring microcopy, calm confidence. Blue is spent ONLY on the single primary or
  "now" element per screen.

  Contract: every class, id, data-attribute, and DOM relationship that app.js renders
  or toggles is restyled here under its EXACT selector, never renamed or removed. The
  grid geometry variables (--time-col, --hour-height) keep their names because app.js
  measures through them (getHourHeight reads --hour-height as px).

  Fonts: Pretendard via dynamic-subset CSS (linked in index.html), font-display swap,
  system fallback in --font so first paint is never blocked. No self-hosted faces here.

  iOS: every text input, textarea, select is >= 16px (below 16px iOS force-zooms).
  Safe-area insets, dynamic viewport (dvh), >= 44px touch targets, theme-color in head.

  No em dash anywhere, including comments. Commas, periods, parentheses only.
*/

/* ==================================================================
   1. TOKENS
   ================================================================== */

:root {
  /* brand + semantic (real Toss palette) */
  --blue: #3182f6;          /* the ONE primary: buttons, today, now-line, focal hero */
  --blue-press: #1b64da;    /* pressed/active state of anything blue */
  --blue-wash: #e8f3ff;     /* light blue fill: selected segment, blue chips, eyebrow */
  --green: #2ba471;         /* positive: completed check, done confirmations */
  --red: #f04452;           /* negative: delete, conflict danger, error toast */
  --red-wash: #fdecee;      /* light red fill behind delete and danger surfaces */
  --amber: #ff9500;         /* warm accent for briefing/nudge icons only, never primary */

  /* greys (surfaces and lines) */
  --bg: #f2f4f6;            /* app background, the calm grey canvas */
  --surface: #ffffff;       /* cards, sheets, blocks, inputs */
  --surface-2: #f9fafb;     /* faint inset: segmented track, time field, digest stat */
  --border: #e5e8eb;        /* card borders, dividers, gridlines */
  --hairline: #eff1f4;      /* faintest separator between rows inside a card */

  /* text (the contrast contract) */
  --t1: #191f28;            /* primary text, titles, numbers, 16.1:1 */
  --t2: #4e5968;            /* secondary body text, the default for sentences, 7.4:1 AA */
  --t3: #8b95a1;            /* tertiary: labels, captions, placeholders, only >= 16px or bold */

  /* company (read-only) accent, quiet locked grey-blue, never the live blue */
  --co-fill: #eef1f4;
  --co-bar: #b0b8c1;
  --co-ink: #555e6c;        /* darkened to ~5:1 on the company fill, passes AA at 13px */

  /* priority dots (calm, restrained) */
  --pri-5: #f04452;         /* high */
  --pri-3: #ff9500;         /* medium */
  --pri-1: #2ba471;         /* low */
  --pri-0: #c2c8ce;         /* none */

  /* radius */
  --r-card: 20px;
  --r-sheet: 28px;
  --r-field: 14px;
  --r-block: 12px;
  --r-btn: 14px;
  --r-pill: 999px;

  /* elevation (soft, light, Toss never heavy) */
  --sh-card: 0 2px 8px rgba(17, 24, 39, 0.04);
  --sh-raised: 0 4px 16px rgba(17, 24, 39, 0.08);
  --sh-sheet: 0 -8px 30px rgba(17, 24, 39, 0.12);
  --sh-hero: 0 8px 24px rgba(49, 130, 246, 0.28);

  /* motion */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-fast: 120ms;
  --dur: 220ms;
  --dur-slow: 320ms;

  /* calendar geometry (app.js reads these as px; keep both numeric) */
  --time-col: 52px;
  --hour-height: 56px;

  /* type stack, carries Hangul + Latin at big bold weights, system fallback first paint */
  --font: "Pretendard Variable", "Pretendard", "Apple SD Gothic Neo",
    -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", Roboto, sans-serif;

  /* safe-area shorthands */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/* Dark tokens, defined now so a later prefers-color-scheme block needs no re-architecting.
   Kept minimal and conservative; the app ships light by default. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #17181c;
    --surface: #1f2024;
    --surface-2: #26272c;
    --border: #33353b;
    --hairline: #2a2c31;
    --t1: #edeff2;
    --t2: #b0b6be;
    --t3: #7a828c;
    --blue: #4593fc;
    --blue-wash: #1a2a40;
    --co-fill: #2a2d33;
    --co-ink: #aab2bc;
    --co-bar: #4a4f57;
    --sh-card: 0 2px 8px rgba(0, 0, 0, 0.3);
    --sh-raised: 0 4px 16px rgba(0, 0, 0, 0.4);
    --sh-sheet: 0 -8px 30px rgba(0, 0, 0, 0.5);
  }
}

/* ==================================================================
   2. RESET + BASE
   ================================================================== */

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  /* kill double-tap zoom (pinch is locked by the viewport meta + the app.js gesture guard);
     normal scroll and the per-block drag/resize touch still work. */
  touch-action: manipulation;
  /* stop pull-to-refresh (a PWA state-losing reload) and bounce scroll-chaining to the page. */
  overscroll-behavior: none;
}

html {
  height: 100%;
}

body {
  /* fixed-height app shell: the body is exactly the viewport so main.layout /
     .calendar-pane resolve to a definite height and .calendar scrolls INTERNALLY.
     min-height here (instead of height) was the bug: the shell grew to fit the full
     24h grid (1440px), so .calendar never got a bounded height to scroll within, and
     its overscroll-behavior:contain then swallowed the wheel so nothing scrolled. */
  height: 100vh;
  height: 100dvh;
  font-family: var(--font);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.55;
  color: var(--t1);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "tnum"; /* tabular figures so clock times do not jiggle */
  -webkit-tap-highlight-color: transparent;
  overflow: hidden;
  /* app shell is a single vertical column: topbar, main, assistant bar */
  display: flex;
  flex-direction: column;
}

/* lock page scroll while a bottom sheet is open (app.js toggles body.sheet-open) */
body.sheet-open {
  overflow: hidden;
}

button {
  font-family: inherit;
}

input,
textarea,
select {
  font-family: inherit;
}

h1,
h2,
h3,
p {
  margin: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

[hidden] {
  display: none !important;
}

::selection {
  background: var(--blue-wash);
  color: var(--blue-press);
}

:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

/* ==================================================================
   3. BUTTONS (.btn base + modifiers)
   ================================================================== */

.btn {
  font-family: var(--font);
  border: none;
  background: transparent;
  cursor: pointer;
  border-radius: var(--r-btn);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--t1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: transform var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  -webkit-tap-highlight-color: transparent;
  /* long-press on a button must not select its label (blue highlight) or pop the iOS
     copy/define callout. Every chrome button (ghost/primary/danger/small/icon/toggle)
     extends this base, so one rule covers them all. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Text fields stay selectable + editable even though the chrome and calendar surfaces
   below turn selection off. This is the narrow-scope counterpart: user-select:none lives
   ONLY on .btn / calendar surfaces / .cal-block, never on body or a field ancestor, and
   this rule explicitly re-asserts selectable text on every input so the command, reply,
   search, tag, and editor fields can be tapped, caret-placed, and selected. Inputs are
   already >= 16px elsewhere so iOS does not zoom on focus. */
input,
textarea,
select,
[contenteditable],
[contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

.btn:active {
  transform: scale(0.97);
}

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

/* primary: the one loud filled blue button per screen */
.btn-primary {
  background: var(--blue);
  color: #fff;
  font-weight: 800;
  height: 54px;
  padding: 0 22px;
  border-radius: var(--r-btn);
  font-size: 17px;
}

.btn-primary:active {
  background: var(--blue-press);
}

/* ghost: the calm secondary (cancel) */
.btn-ghost {
  background: var(--surface-2);
  color: var(--t2);
  font-weight: 700;
}

.btn-ghost:hover {
  background: var(--border);
}

/* danger: delete */
.btn-danger {
  background: var(--red-wash);
  color: var(--red);
  font-weight: 700;
}

.btn-danger:hover {
  background: #fbdde1;
}

/* small: compact actions (quick-add +, filters, msg actions, send) */
.btn-small {
  height: 44px;
  padding: 0 16px;
  font-size: 15px;
  border-radius: var(--r-field);
}

/* icon: square transparent glyph button (prev/next/close/settings/reload).
   40px keeps a comfortable tap target while leaving the topbar room for the
   wordmark on a phone. */
.btn-icon {
  width: 38px;
  height: 40px;
  padding: 0;
  background: transparent;
  color: var(--t2);
  border-radius: var(--r-field);
  font-size: 18px;
  line-height: 1;
}

.btn-icon:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* chev: prev/next chevrons, same family as icon */
.btn-chev {
  width: 36px;
  height: 40px;
  padding: 0;
  background: transparent;
  color: var(--t2);
  border-radius: var(--r-field);
  font-size: 22px;
  line-height: 1;
  font-weight: 600;
}

.btn-chev:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* toggle: segmented tab button (view toggle, presets) */
.btn-toggle {
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  color: var(--t3);
  padding: 8px 12px;
  min-height: 36px;
  border-radius: 10px;
  letter-spacing: -0.01em;
}

.btn-toggle.is-active {
  background: var(--blue-wash);
  color: var(--blue);
}

/* ==================================================================
   4. TOP BAR, MASTHEAD, SEARCH, COMMAND
   ================================================================== */

header.topbar {
  flex: 0 0 auto;
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--bg);
  padding: calc(10px + var(--safe-top)) max(16px, var(--safe-left)) 10px
    max(16px, var(--safe-right));
}

.topbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* wordmark: Demerzel with a blue dot accent (the Toss spark idea as a calm dot) */
.brand {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.035em;
  color: var(--t1);
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  white-space: nowrap;
  /* the brand is the one element that yields when the bar is tight: it shrinks /
     truncates so the action buttons (오늘 / chevrons / icons) never wrap or clip. */
  flex: 0 1 auto;
  min-width: 0;
}

/* let the wordmark ellipsize instead of pushing the row wider (last-resort on tiny
   screens). spark + dot stay; only the long word truncates. */
.brand-word {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.brand-dot {
  color: var(--blue);
  flex: none;
}

/* the Bloom app-mark: a rounded chip showing the same artwork as the installed icon.
   the SVG paints its own dark background, so no fill here, just the rounded clip. */
.spark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  flex: none;
  width: 27px;
  height: 27px;
  margin-right: 8px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(20, 26, 40, 0.35);
}
.spark svg {
  width: 100%;
  height: 100%;
  display: block;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 1px;
  /* the action cluster keeps its full width; the brand yields instead. */
  flex: 0 0 auto;
}

/* every action button keeps its intrinsic size (no shrink, no wrap) so a tight bar
   can never squeeze a button until its label wraps to two lines and clips. */
.topbar-actions > .btn,
.topbar-actions > .mh-overflow {
  flex: 0 0 auto;
}

/* "오늘" reads as a quiet pill text button, not a chevron */
#btn-today.btn {
  height: 40px;
  padding: 0 12px;
  margin-right: 1px;
  background: var(--surface-2);
  color: var(--t2);
  border-radius: var(--r-pill);
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
}

#btn-today.btn:hover {
  background: var(--border);
}

/* overflow group (reload / command / settings) sits flush right */
.mh-overflow {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

/* narrow phones: the Korean system font renders "오늘" wider than desktop, and safe
   area insets eat width. Trim the wordmark and the today pill a touch so the whole
   top row fits on one line without the brand having to truncate. */
@media (max-width: 400px) {
  .brand {
    font-size: 20px;
  }
  .spark {
    width: 23px;
    height: 23px;
    margin-right: 6px;
  }
  #btn-today.btn {
    padding: 0 9px;
  }
}

/* masthead: date headline + view toggle. On wide screens they share one row (date left,
   toggle right). When they do not fit, the toggle WRAPS to its own row instead of
   overlapping the date (flex-wrap), and the date stays on one line (nowrap). */
.masthead {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0 2px;
  flex-wrap: wrap;
}

.range-label {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--t1);
  line-height: 1.2;
  min-width: 0;
  white-space: nowrap;
}

.mh-spacer {
  flex: 1 1 auto;
}

.view-toggle {
  display: inline-flex;
  gap: 4px;
  background: var(--surface);
  border-radius: var(--r-field);
  padding: 4px;
  box-shadow: var(--sh-card);
  flex: 0 0 auto;
}

/* phones: the view toggle gets its own full-width row under the date (it cannot sit
   beside a date headline on a narrow screen without colliding). */
@media (max-width: 540px) {
  .masthead {
    row-gap: 8px;
  }
  .mh-spacer {
    display: none;
  }
  .range-label {
    font-size: 20px;
  }
  .view-toggle {
    width: 100%;
    justify-content: space-between;
  }
  .view-toggle .btn-toggle {
    flex: 1 1 0;
  }
}

/* search bar: rounded surface field with a clear x when non-empty */
.search-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-field);
  padding: 0 12px 0 14px;
  height: 48px;
  transition: border-color var(--dur-fast) var(--ease);
}

.search-bar:focus-within {
  border-color: var(--blue);
}

/* leading magnifier glyph, drawn with CSS so no asset is needed */
.search-bar::before {
  content: "";
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  background: var(--t3);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='11' cy='11' r='7' fill='none' stroke='black' stroke-width='2'/><path d='M20 20l-3.5-3.5' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='11' cy='11' r='7' fill='none' stroke='black' stroke-width='2'/><path d='M20 20l-3.5-3.5' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
}

.search-input {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--font);
  font-size: 16px; /* iOS floor */
  font-weight: 500;
  color: var(--t1);
}

.search-input::placeholder {
  color: var(--t3);
}

/* clear x button inside the search bar */
.search-clear {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.05);
  color: var(--t2);
  font-size: 17px;
}

.search-clear:hover {
  background: rgba(0, 0, 0, 0.09);
}

/* command bar: a thin secondary path, collapsed on mobile, revealed by body.cmd-open.
   The bottom assistant composer is the primary input surface. */
.command-bar {
  display: none;
  align-items: flex-end;
  gap: 8px;
  margin-top: 12px;
}

body.cmd-open .command-bar {
  display: flex;
}

.command-input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font);
  font-size: 16px; /* iOS floor */
  font-weight: 500;
  line-height: 1.5;
  color: var(--t1);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-field);
  padding: 12px 14px;
  outline: none;
  resize: none;
}

.command-input:focus {
  border-color: var(--blue);
}

.command-input::placeholder {
  color: var(--t3);
}

.command-bar .btn-primary {
  height: 48px;
  flex: 0 0 auto;
  font-size: 15px;
  padding: 0 18px;
}

.command-status {
  font-size: 13px;
  font-weight: 600;
  color: var(--t3);
  margin-top: 6px;
  min-height: 0;
}

.command-status:empty {
  margin-top: 0;
}

/* auto-grow textareas (app.js calls autoGrowInput); cap so they never run away */
.grow-input {
  max-height: 120px;
  overflow-y: auto;
}

/* ==================================================================
   5. LAYOUT (main, calendar pane, backlog pane)
   ================================================================== */

main.layout {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* on a phone the calendar pane is the body; list view swaps to the backlog pane */
.calendar-pane {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* in list view, hide the calendar pane entirely and let the backlog pane fill */
body.view-list .calendar-pane {
  display: none;
}

.backlog-pane {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* list view scrolls here; keep the bounce/pull-to-refresh in this pane, not the page. */
  overscroll-behavior: contain;
  background: var(--bg);
  padding: 8px max(16px, var(--safe-left)) 8px max(16px, var(--safe-right));
}

/* outside list view, the backlog has no place on a phone calendar screen: the calendar
   owns the screen and the assistant bar handles capture, so the backlog lives in the List
   tab. Hidden here, re-shown as a side panel on a wide screen (see the 720px media query).
   This only hides it in calendar views; list view keeps the pane (rule below). */
body:not(.view-list) .backlog-pane {
  display: none;
}

/* in list view the backlog pane is the whole canvas */
body.view-list .backlog-pane {
  flex: 1 1 auto;
  max-height: none;
  border-top: none;
}

/* per-view density tuning (app.js sets these body classes; rules are optional polish).
   A single-day view has the whole width for one column, so blocks can breathe a touch more;
   the week view is the tightest, so titles tuck tighter. Behavior is unchanged. */
body.view-day .cal-block {
  left: 6px;
  right: 6px;
}

body.view-week .blk-title,
body.view-3day .blk-title {
  letter-spacing: -0.03em;
}

body.view-week .cal-hourlabel,
body.view-3day .cal-hourlabel {
  font-size: 11px;
}

.backlog-head {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg);
  padding-top: 4px;
}

.backlog-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 4px 2px 10px;
}

.backlog-head-row h2 {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--t1);
}

/* quick add: a compact pill input + round blue plus */
.quick-add {
  display: flex;
  gap: 8px;
  align-items: center;
}

.quick-add-input {
  font-family: var(--font);
  font-size: 16px; /* iOS floor */
  font-weight: 500;
  line-height: 1.4;
  color: var(--t1);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-pill);
  padding: 9px 14px;
  outline: none;
  resize: none;
  width: 150px;
  max-width: 46vw;
}

.quick-add-input:focus {
  border-color: var(--blue);
}

.quick-add-input::placeholder {
  color: var(--t3);
}

.quick-add .btn {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  background: var(--blue);
  color: #fff;
  font-size: 24px;
  font-weight: 600;
  line-height: 1;
}

.quick-add .btn:active {
  background: var(--blue-press);
}

/* ==================================================================
   6. LIST CONTROLS (presets + filters), list view only
   ================================================================== */

.list-controls {
  margin: 0 2px 8px;
}

.list-controls-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

/* preset bar shares the segmented look on a floating surface track */
.preset-bar {
  display: inline-flex;
  gap: 4px;
  background: var(--surface);
  border-radius: var(--r-field);
  padding: 4px;
  box-shadow: var(--sh-card);
  flex: 1 1 auto;
}

.preset-btn {
  flex: 1 1 0;
}

.filter-toggle {
  flex: 0 0 auto;
  background: var(--surface-2);
  color: var(--t2);
  height: 44px;
  padding: 0 14px;
  font-size: 14px;
  font-weight: 700;
  border-radius: var(--r-field);
}

/* when filters are active the toggle carries a blue tint so it is not a hidden trap */
.filter-toggle.has-active {
  background: var(--blue-wash);
  color: var(--blue);
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 4px 0 4px;
}

.filter-select {
  flex: 1 1 140px;
  min-width: 120px;
}

.filter-bar .btn-small {
  flex: 0 0 auto;
  background: var(--surface-2);
  color: var(--t2);
}

/* ==================================================================
   7. CALENDAR (the controlled-density surface)
   ================================================================== */

/* The calendar surfaces turn off text selection and the iOS callout so dragging,
   resizing, or long-pressing a block never grabs a blue text selection or pops the
   copy/define bubble. Editor inputs live in the modal, outside these surfaces, and the
   input rule above keeps them selectable regardless. */
.calendar,
.calendar-allday,
.month-grid {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* all-day strip: a quiet horizontal scroll row of read-only company chips */
.calendar-allday {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px max(16px, var(--safe-left)) 8px max(16px, var(--safe-right));
  background: var(--bg);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.calendar-allday::-webkit-scrollbar {
  display: none;
}

/* collapse to nothing when empty (no empty label) */
.calendar-allday:empty {
  display: none;
}

.allday-chip {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  background: var(--co-fill);
  color: var(--co-ink);
  position: relative;
}

/* company all-day chip: a tiny lock glyph prefix says "not mine" */
.allday-chip.is-cal {
  padding-left: 26px;
}

.allday-chip.is-cal::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 11px;
  height: 11px;
  background: var(--co-bar);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 10V8a6 6 0 1112 0v2h1a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2h1zm2 0h8V8a4 4 0 10-8 0v2z'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 10V8a6 6 0 1112 0v2h1a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2h1zm2 0h8V8a4 4 0 10-8 0v2z'/></svg>") center / contain no-repeat;
}

/* my multi-day task chip in the all-day strip: a white card with a thin blue spine */
.allday-chip.is-task {
  background: var(--surface);
  color: var(--t1);
  font-weight: 700;
  box-shadow: var(--sh-card), inset 3px 0 0 var(--blue);
  cursor: pointer;
}

.allday-chip.is-task.is-done {
  opacity: 0.55;
  box-shadow: var(--sh-card), inset 3px 0 0 var(--border);
  text-decoration: line-through;
}

.allday-span {
  color: var(--t3);
  font-weight: 600;
}

/* the time grid scroll container */
.calendar {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  background: var(--bg);
  -webkit-overflow-scrolling: touch;
  /* keep the bounce/pull-to-refresh inside this scroller; do not chain to the page. */
  overscroll-behavior: contain;
  /* app.js manages touch scrolling/momentum on blocks; keep native scroll otherwise.
     pan-y here only works because .cal-block.is-task and .blk-resize set touch-action:none,
     so a touch starting on a draggable block goes to app.js, not native pan. */
  touch-action: pan-y;
}

/* the grid: app.js sets grid-template-columns inline (var(--time-col) repeat(N,1fr)) */
.cal-grid {
  display: grid;
  position: relative;
  padding: 8px max(14px, var(--safe-right)) 24px 0;
}

.cal-corner {
  position: sticky;
  top: 0;
  z-index: 6;
  background: var(--bg);
}

/* day header row: dow over a date number, today highlighted blue */
.cal-dayhead {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  text-align: center;
  padding: 2px 0 8px;
}

.dh-dow {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: var(--t3);
  letter-spacing: 0.01em;
}

.dh-date {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-top: 3px;
  border-radius: 50%;
  font-size: 18px;
  font-weight: 800;
  color: var(--t1);
}

.cal-dayhead.is-today .dh-dow {
  color: var(--blue);
}

.cal-dayhead.is-today .dh-date {
  background: var(--blue);
  color: #fff;
}

/* the time label column */
.cal-timecol {
  position: relative;
}

.cal-hourlabel {
  height: var(--hour-height);
  position: relative;
  top: -8px; /* ride the hour line */
  text-align: right;
  padding-right: 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--t2); /* AA: hour labels were --t3 (3.04:1), now --t2 (7.4:1) */
  letter-spacing: -0.01em;
}

/* day column: white-ish only by gridline so the grey canvas breathes.
   app.js appends N .cal-hourcell background cells, each drawing a top hour line. */
.cal-daycol {
  position: relative;
}

.cal-hourcell {
  height: var(--hour-height);
  border-top: 1px solid var(--border);
}

.cal-hourcell:first-child {
  border-top-color: transparent;
}

/* time-grid block: a soft rounded slab, app.js sets top/height (and inline left/width
   for overlap lanes). Base rule must NOT fight inline lane styles, so only set the
   single-lane left/right here. */
.cal-block {
  position: absolute;
  left: 5px;
  right: 5px;
  border-radius: var(--r-block);
  padding: 7px 10px 6px;
  overflow: hidden;
  line-height: 1.2;
  box-shadow: var(--sh-card);
  cursor: pointer;
  z-index: 2;
  /* dragging or long-pressing a block must not select its title (blue highlight) or pop
     the iOS callout. Applies to both .is-task and read-only .is-cal blocks. */
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

.blk-title {
  /* wrap titles (up to 3 lines, then clipped by the block height) so narrow or
     overlapping blocks show the title rather than collapsing to one character. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  font-size: 13px;
  font-weight: 700;
  color: var(--t1);
  letter-spacing: -0.02em;
  overflow: hidden;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.blk-time {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--t2); /* darker: fits WCAG AA at this size and reads better than --t3 */
  margin-top: 1px;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* time sits below the title, under the check, so it needs far less left clearance */
.cal-block.is-task .blk-time {
  padding-left: 4px;
}

/* compressed multi-day columns: a touch smaller still */
body.view-week .blk-time,
body.view-3day .blk-time {
  font-size: 9.5px;
}

/* my task: white fill, thin blue spine via inset shadow so the radius is preserved.
   Blue is spent ONLY on the spine, so a packed day stays a calm field of white cards. */
.cal-block.is-task {
  background: var(--surface);
  box-shadow: var(--sh-card), inset 3px 0 0 var(--blue);
  /* REQUIRED: app.js binds pointerdown/move on each task block and owns the touch
     (preventDefault + manual el.calendar.scrollTop + setPointerCapture) for longpress,
     drag, resize, and inertial manual scroll. The browser must not pan/zoom on it.
     Set ONLY on .is-task; read-only .is-cal company blocks keep default touch behavior. */
  touch-action: none;
  cursor: grab;
}

/* make room for the quick-complete check pinned top-left (title only; the time
   sits on the next line below the check and keeps its small left padding) */
.cal-block.is-task .blk-title {
  padding-left: 18px;
}

/* company block: cool fill, grey spine, no shadow, a lock glyph top-right */
.cal-block.is-cal {
  background: var(--co-fill);
  box-shadow: inset 3px 0 0 var(--co-bar);
}

.cal-block.is-cal .blk-title {
  color: var(--co-ink);
}

.cal-block.is-cal .blk-time {
  color: var(--co-ink);
  opacity: 0.75;
}

.cal-block.is-cal::after {
  content: "";
  position: absolute;
  top: 8px;
  right: 8px;
  width: 11px;
  height: 11px;
  background: var(--co-bar);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 10V8a6 6 0 1112 0v2h1a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2h1zm2 0h8V8a4 4 0 10-8 0v2z'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 10V8a6 6 0 1112 0v2h1a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2h1zm2 0h8V8a4 4 0 10-8 0v2z'/></svg>") center / contain no-repeat;
}

/* done: faded, struck through, spine fades to a hairline */
.cal-block.is-done {
  opacity: 0.55;
}

.cal-block.is-done .blk-title {
  text-decoration: line-through;
  color: var(--t3);
}

.cal-block.is-done.is-task {
  box-shadow: var(--sh-card), inset 3px 0 0 var(--border);
}

/* short block (app.js adds .is-short under ~36px): tighten and hide the time line */
.cal-block.is-short {
  padding: 4px 10px;
}

.cal-block.is-short .blk-title {
  font-size: 12px;
}

.cal-block.is-short .blk-time {
  display: none;
}

/* recurring badge before a title */
.recur-badge {
  color: var(--t3);
  margin-right: 4px;
  font-weight: 700;
}

.cal-block.is-cal .recur-badge {
  color: var(--co-ink);
}

/* quick-complete check on a block: a small ring that fills green when done.
   A transparent expanded hit area keeps the tap target comfortable (>= 44px). */
.blk-check {
  position: absolute;
  top: 7px;
  left: 7px;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: transparent;
  cursor: pointer;
  z-index: 3;
}

.blk-check::before {
  content: "";
  position: absolute;
  top: -12px;
  left: -12px;
  right: -12px;
  bottom: -12px;
}

.blk-check[aria-checked="true"] {
  background: var(--green);
  border-color: var(--green);
}

.blk-check[aria-checked="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12.5l4.5 4.5L19 7' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 13px no-repeat;
}

/* drag and resize feel (app.js attaches handlers and toggles these classes) */
.cal-block.is-dragging {
  box-shadow: var(--sh-raised);
  transform: scale(1.02);
  opacity: 0.92;
  z-index: 12;
}

.cal-block.is-resizing {
  box-shadow: var(--sh-raised);
  z-index: 12;
}

/* live snapped-time pill that follows a dragging/resizing block */
.blk-dragtime {
  position: absolute;
  top: 4px;
  right: 6px;
  z-index: 4;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
  background: var(--blue);
  padding: 2px 7px;
  border-radius: 7px;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 1px 4px rgba(49, 130, 246, 0.4);
}

/* resize handles: 8px hit zones at the block edges (app.js appends .blk-resize-top/bottom).
   A faint grab bar appears on hover, and always on short blocks so users know they resize. */
.blk-resize {
  position: absolute;
  left: 0;
  right: 0;
  height: 10px;
  z-index: 3;
  cursor: row-resize;
  /* REQUIRED: app.js binds pointerdown/move on the handle (preventDefault +
     setPointerCapture) so the 10px edge zone owns the touch for resize; the browser
     must not scroll or zoom on it. */
  touch-action: none;
}

.blk-resize-top {
  top: -2px;
}

.blk-resize-bottom {
  bottom: -2px;
}

.blk-resize::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 2px;
  width: 24px;
  height: 3px;
  border-radius: 2px;
  background: var(--border);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}

.blk-resize-top::after {
  top: 2px;
  bottom: auto;
}

.cal-block:hover .blk-resize::after {
  opacity: 1;
}

.cal-block.is-short .blk-resize-bottom::after {
  opacity: 0.6; /* always-visible faint bottom grip on short blocks */
}

/* now line: a thin blue rule with a dot on today's column */
.cal-now {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  /* 블록(z-index 2) 위에는 그리되, sticky 한 날짜 헤더(.cal-dayhead z-index 5 / .cal-corner 6)
     아래에 둔다. 그리드를 스크롤해 현재 시각선이 맨 위로 올라오면 불투명한 헤더가 선을 덮어
     가려야 하는데, 예전 z-index 9 는 헤더보다 높아 선이 헤더(날짜) 위로 비어져 나왔다. */
  z-index: 4;
  pointer-events: none;
}

.cal-now::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  border-top: 2px solid var(--blue);
}

.cal-now::after {
  content: "";
  position: absolute;
  left: -4px;
  top: -5px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--blue);
  box-shadow: 0 0 0 3px rgba(49, 130, 246, 0.18);
}

/* ==================================================================
   8. MONTH VIEW
   ================================================================== */

.month-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 8px max(14px, var(--safe-left)) 16px max(14px, var(--safe-right));
  background: var(--bg);
  /* parity + future-proofing: a no-op while overflow is hidden, but keeps scroll-chaining
     contained if the month body ever scrolls internally. */
  overscroll-behavior: contain;
}

.month-weekhead {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 6px;
  flex: 0 0 auto;
}

.month-weekhead-cell {
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--t3);
  letter-spacing: 0.01em;
}

.month-weekhead-cell.is-weekend {
  color: #aeb6be;
}

.month-body {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.month-cell {
  background: var(--surface);
  border-radius: 10px;
  padding: 5px 5px 4px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  box-shadow: var(--sh-card);
  min-height: 0;
  overflow: hidden;
}

.month-cell.is-othermonth {
  background: transparent;
  box-shadow: none;
  opacity: 0.55;
}

.month-daynum {
  align-self: flex-start;
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  color: var(--t1);
  line-height: 1.1;
  padding: 0;
  min-width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
}

.month-cell.is-othermonth .month-daynum {
  color: var(--t3);
}

.month-cell.is-today .month-daynum {
  background: var(--blue);
  color: #fff;
  font-weight: 800;
}

.month-chips {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 0;
  overflow: hidden;
}

.month-chip {
  display: flex;
  align-items: center;
  gap: 3px;
  border: none;
  background: var(--blue-wash);
  cursor: pointer;
  text-align: left;
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.01em;
  padding: 2px 5px;
  border-radius: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.month-chip.is-task {
  background: var(--blue-wash);
  color: var(--blue-press);
}

.month-chip.is-cal {
  background: var(--co-fill);
  color: var(--co-ink);
}

.month-chip.is-done {
  text-decoration: line-through;
  opacity: 0.55;
}

.month-chip-time {
  font-weight: 600;
  opacity: 0.7;
  flex: 0 0 auto;
}

.month-chip .recur-badge {
  margin-right: 0;
}

.month-more {
  align-self: flex-start;
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  color: var(--t3);
  padding: 0 4px;
}

/* ==================================================================
   9. BACKLOG + LIST ROWS
   ================================================================== */

.backlog-list {
  padding-bottom: 8px;
}

.backlog-section-label {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--t3);
  margin: 16px 4px 10px;
}

.backlog-list .backlog-section-label:first-child {
  margin-top: 4px;
}

/* each row is its own soft card, the Toss feel */
.backlog-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: var(--surface);
  border-radius: 16px;
  padding: 14px;
  margin-bottom: 8px;
  box-shadow: var(--sh-card);
}

.backlog-check {
  position: relative;
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  margin-top: 1px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: transparent;
  cursor: pointer;
}

/* enlarge the tap target without growing the visual ring */
.backlog-check::before {
  content: "";
  position: absolute;
  top: -11px;
  left: -11px;
  right: -11px;
  bottom: -11px;
}

.backlog-item.is-done .backlog-check {
  background: var(--green);
  border-color: var(--green);
}

.backlog-item.is-done .backlog-check::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12.5l4.5 4.5L19 7' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 14px no-repeat;
}

.backlog-body {
  flex: 1 1 auto;
  min-width: 0;
  cursor: pointer;
}

.backlog-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--t1);
  line-height: 1.35;
  word-break: break-word;
}

.backlog-item.is-done .backlog-title {
  text-decoration: line-through;
  color: var(--t3);
}

.backlog-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin-top: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--t3);
}

.backlog-time {
  color: var(--t2);
  font-weight: 700;
}

.backlog-empty {
  text-align: center;
  color: var(--t3);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.6;
  padding: 48px 24px;
}

/* tag chip (read-only display in meta, and in the editor tag box) */
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--blue-press);
  background: var(--blue-wash);
  border-radius: var(--r-pill);
  padding: 4px 10px;
}

/* priority dots */
.pri-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: 0 0 auto;
}

.pri-dot.pri-5 {
  background: var(--pri-5);
}

.pri-dot.pri-3 {
  background: var(--pri-3);
}

.pri-dot.pri-1 {
  background: var(--pri-1);
}

.pri-dot.pri-0 {
  background: var(--pri-0);
}

/* ==================================================================
   10. ASSISTANT BOTTOM BAR (persistent)
   ================================================================== */

.asst-bar {
  flex: 0 0 auto;
  position: sticky;
  bottom: 0;
  z-index: 25;
  background: var(--bg);
  padding: 10px max(16px, var(--safe-left)) calc(12px + var(--safe-bottom))
    max(16px, var(--safe-right));
  box-shadow: 0 -1px 0 var(--border);
}

/* collapsed status line: a calm single sentence the user can glance at */
.asst-bar-status {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: var(--surface);
  border: none;
  border-radius: var(--r-pill);
  box-shadow: var(--sh-raised);
  padding: 11px 14px;
  margin-bottom: 10px;
  cursor: pointer;
  font-family: var(--font);
  text-align: left;
}

.asst-bar-status:active {
  transform: scale(0.99);
}

.asst-bar-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--blue);
  flex: 0 0 auto;
  animation: breathe 3.2s ease-in-out infinite;
}

.asst-bar-line {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--t1);
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.asst-bar-open {
  color: var(--t3);
  flex: 0 0 auto;
  font-size: 17px;
  line-height: 1;
}

/* composer, always visible, reads like a chat input */
.asst-bar-form {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.asst-bar-now {
  flex: 0 0 auto;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  color: var(--blue);
  background: var(--blue-wash);
  border: none;
  border-radius: var(--r-pill);
  padding: 0 15px;
  height: 48px;
  cursor: pointer;
  letter-spacing: -0.01em;
}

.asst-bar-now:active {
  background: #d6e9ff;
}

.asst-bar-input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font);
  font-size: 16px; /* iOS floor */
  font-weight: 500;
  line-height: 1.4;
  color: var(--t1);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 22px;
  padding: 12px 16px;
  outline: none;
  resize: none;
}

.asst-bar-input:focus {
  border-color: var(--blue);
}

.asst-bar-input::placeholder {
  color: var(--t3);
}

/* send button (a .btn.btn-small in markup): make it the blue chat send */
.asst-bar-send {
  flex: 0 0 auto;
  height: 48px;
  min-height: 0;
  padding: 0 16px;
  background: var(--blue);
  color: #fff;
  font-weight: 800;
  font-size: 15px;
  border-radius: var(--r-pill);
}

.asst-bar-send:active {
  background: var(--blue-press);
}

@keyframes breathe {
  0%,
  100% {
    opacity: 0.5;
    transform: scale(0.82);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
}

/* ==================================================================
   11. MODALS + BOTTOM SHEETS (shared mechanics)
   ================================================================== */

/* scrim, bottom-aligns its card on phones (sheet feel), centers on wider screens */
.modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(15, 18, 22, 0.42);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  animation: scrim-in var(--dur) var(--ease);
}

@keyframes scrim-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* the card: a sheet with rounded top corners, lifts off the page */
.modal-card,
.inbox-card {
  background: var(--bg);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  box-shadow: var(--sh-sheet);
  max-height: 92vh;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  padding-bottom: var(--safe-bottom);
  width: 100%;
}

/* editor and settings cards just pop (fade + slight rise) */
#task-modal .modal-card,
#settings-modal .modal-card {
  animation: sheet-pop var(--dur-slow) var(--ease);
}

@keyframes sheet-pop {
  from {
    transform: translateY(18px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* grab pill at the top of a sheet */
.sheet-handle {
  width: 40px;
  height: 5px;
  border-radius: 3px;
  background: #d1d6db;
  margin: 10px auto 4px;
  flex: 0 0 auto;
  /* REQUIRED: app.js attachSheetSwipe binds pointerdown/move on #inbox-handle (this pill)
     and drives the card translateY for swipe-to-close; native scroll/zoom must not fight it. */
  touch-action: none;
  cursor: grab;
}

/* ----- editor card chrome ----- */
.editor-card {
  padding-left: max(0px, var(--safe-left));
  padding-right: max(0px, var(--safe-right));
}

.editor-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 20px 8px;
  flex: 0 0 auto;
}

.editor-head h2 {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--t1);
}

.editor-occ-note {
  margin: 0 20px 12px;
  padding: 11px 14px;
  background: var(--blue-wash);
  color: var(--blue-press);
  border-radius: var(--r-field);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.45;
  flex: 0 0 auto;
}

/* the editor body scrolls between the sticky head and the sticky footer.
   The editor card has no dedicated scroll wrapper, so make the card scroll its fields
   while keeping head and the sticky actions in place. */
.editor-card {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* keep the editor sheet scroll from chaining/leaking to the page behind the modal. */
  overscroll-behavior: contain;
}

/* settings card padding */
#settings-modal .modal-card {
  padding: 8px 20px 20px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* keep the settings sheet scroll from chaining/leaking to the page behind the scrim. */
  overscroll-behavior: contain;
}

#settings-modal h2 {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--t1);
  margin: 8px 0 6px;
}

.modal-help {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--t2);
  line-height: 1.55;
  margin-bottom: 18px;
}

.modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 8px;
}

.modal-actions .btn-ghost {
  flex: 0 0 auto;
  height: 54px;
  padding: 0 22px;
  font-size: 16px;
}

.modal-actions .btn-primary {
  flex: 1 1 auto;
}

.field-hint {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--t3);
}

/* 설정 모달의 "Assistant memory" 목록: remember 된 항목들을 펼쳐 보여준다. */
.memory-list {
  margin-top: 8px;
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border, #e5e8eb);
  border-radius: 12px;
  padding: 10px 12px;
  font-size: 13.5px;
  color: var(--t2);
  line-height: 1.5;
}

.memory-item {
  padding: 8px 0;
}

.memory-item + .memory-item {
  border-top: 1px solid var(--border, #eef1f4);
}

.memory-ts {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--t3);
  margin-bottom: 2px;
}

.memory-text {
  color: var(--t1);
  font-weight: 500;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ==================================================================
   12. FORM FIELDS (iOS-safe, 16px floor)
   ================================================================== */

.field {
  display: block;
  margin: 0 20px 20px;
}

.editor-card .field:first-of-type {
  margin-top: 4px;
}

.field-label {
  display: block;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--t2);
  margin: 0 2px 9px;
}

.field-input {
  width: 100%;
  font-family: var(--font);
  font-size: 16px; /* HARD iOS floor */
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.5;
  color: var(--t1);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-field);
  padding: 14px 16px;
  outline: none;
  transition: border-color var(--dur-fast) var(--ease);
  -webkit-appearance: none;
  appearance: none;
}

.field-input:focus {
  border-color: var(--blue);
}

.field-input::placeholder {
  color: var(--t3);
}

textarea.field-input {
  resize: none;
  min-height: 52px;
}

/* select gets a chevron affordance */
.field-select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 9l6 6 6-6' fill='none' stroke='%238B95A1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 18px;
  padding-right: 40px;
}

/* date and time inputs keep the 16px floor */
input[type="date"].field-input,
input[type="time"].field-input,
input[type="number"].field-input {
  font-size: 16px;
}

/* segmented control (editor): white-chip-on-grey active (in-form choice) */
.seg {
  display: flex;
  gap: 6px;
  background: var(--surface-2);
  border-radius: var(--r-field);
  padding: 5px;
}

.seg-btn {
  flex: 1 1 0;
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--t3);
  padding: 11px 4px;
  min-height: 44px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.seg-btn.is-active {
  background: var(--surface);
  color: var(--t1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
}

/* tag input box: a framed surface holding removable chips + a borderless input */
.tag-input {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-field);
  padding: 11px 12px;
  transition: border-color var(--dur-fast) var(--ease);
}

.tag-input:focus-within {
  border-color: var(--blue);
}

/* the chips container is display:contents so chips lay out in the flex row */
.tag-input-chips {
  display: contents;
}

/* removable chip in the editor (the read-only .tag-chip rule above supplies the base) */
.tag-input .tag-chip {
  padding: 6px 8px 6px 11px;
}

.tag-chip-remove {
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--blue-press);
  font-size: 16px;
  line-height: 1;
  padding: 0 2px;
  opacity: 0.7;
}

.tag-chip-remove:hover {
  opacity: 1;
}

.tag-input-field {
  flex: 1 1 90px;
  min-width: 90px;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--font);
  font-size: 16px; /* iOS floor */
  font-weight: 500;
  color: var(--t1);
}

.tag-input-field::placeholder {
  color: var(--t3);
}

/* date/time sub-fields share the field look at the same 16px floor */
.editor-sched-fields {
  margin-top: 12px;
}

.subfield {
  display: block;
}

.subfield-row {
  display: flex;
  gap: 12px;
}

.subfield-row .subfield {
  flex: 1 1 0;
}

.editor-sched-fields .subfield {
  margin-bottom: 12px;
}

.editor-sched-fields .subfield:last-child {
  margin-bottom: 0;
}

.subfield-label {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--t3);
  margin: 0 2px 7px;
  letter-spacing: -0.01em;
}

/* recurrence controls */
.editor-recur-row {
  display: flex;
  gap: 10px;
  align-items: flex-end;
}

.editor-recur-row .field-select {
  flex: 1 1 auto;
}

.recur-interval {
  flex: 0 0 auto;
  width: 96px;
}

.recur-interval .field-input {
  padding: 13px 10px;
  text-align: center;
}

/* weekday picker: seven small pill toggles driven by hidden checkboxes */
.recur-byday {
  display: flex;
  gap: 6px;
  margin-top: 12px;
  flex-wrap: wrap;
}

.byday-box {
  position: relative;
  cursor: pointer;
}

.byday-box input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.byday-box span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--t2);
  font-size: 14px;
  font-weight: 700;
  transition: background-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.byday-box input:checked + span {
  background: var(--blue);
  color: #fff;
}

.byday-box input:focus-visible + span {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

.recur-end {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
  align-items: center;
}

.recur-end .field-select {
  flex: 1 1 140px;
  min-width: 140px;
}

.recur-end-val {
  flex: 1 1 130px;
}

/* sticky footer of the editor */
.editor-actions {
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: var(--bg);
  padding: 14px 20px calc(10px + var(--safe-bottom));
  display: flex;
  align-items: center;
  gap: 12px;
  border-top: 1px solid var(--border);
  flex: 0 0 auto;
}

/* in the editor footer, delete is a square 54px icon-or-text button */
.editor-actions .btn-danger {
  width: 54px;
  height: 54px;
  flex: 0 0 auto;
  padding: 0;
  border-radius: var(--r-btn);
  font-size: 14px;
}

.editor-actions-right {
  flex: 1 1 auto;
  display: flex;
  gap: 10px;
}

.editor-actions-right .btn-ghost {
  flex: 0 0 auto;
  height: 54px;
  padding: 0 22px;
  font-size: 16px;
}

.editor-actions-right .btn-primary {
  flex: 1 1 auto;
}

/* ==================================================================
   13. INBOX SHEET (the Toss home)
   ================================================================== */

/* only this sheet animates via .is-open (slide up); base is translated down */
.inbox-sheet-modal .inbox-card {
  transform: translateY(100%);
  transition: transform var(--dur-slow) var(--ease);
}

.inbox-sheet-modal.is-open .inbox-card {
  transform: translateY(0);
}

/* the inbox modal does not use the shared scrim pop; its card slides */
.inbox-sheet-modal #task-modal-noop {
  /* placeholder to keep specificity notes tidy; no rule needed */
}

.inbox-card {
  max-height: 92vh;
  max-height: 92dvh;
}

.inbox-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 20px 12px;
  flex: 0 0 auto;
}

.inbox-head h2 {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--t1);
}

/* the close x in the inbox head (a .btn.btn-ghost.btn-icon) reads as a round chip */
.inbox-head .btn-icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.05);
  color: var(--t2);
  font-size: 18px;
}

.inbox-head .btn-icon:hover {
  background: rgba(0, 0, 0, 0.09);
}

/* quick-action chips row */
.inbox-quick {
  display: flex;
  gap: 8px;
  padding: 0 20px 10px;
  flex: 0 0 auto;
}

/* .inbox-q in markup is .btn.btn-small; restyle to a calm white pill */
.inbox-q {
  flex: 0 0 auto;
  height: 40px;
  min-height: 0;
  padding: 0 15px;
  font-size: 14px;
  font-weight: 700;
  color: var(--t2);
  background: var(--surface);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-card);
}

.inbox-q:active {
  background: var(--surface-2);
}

/* the scrollable feed, grey so bubbles inside pop. flex column so align-self drives
   left/right bubble placement and .thread-day centers cleanly. */
.inbox-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* keep the inbox feed bounce/pull-to-refresh inside the sheet, not chained to the page. */
  overscroll-behavior: contain;
  padding: 0 16px 14px;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

/* reply composer at the bottom of the sheet, mirrors the bottom bar */
.inbox-reply {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 10px 16px calc(12px + var(--safe-bottom));
  flex: 0 0 auto;
  background: var(--bg);
  border-top: 1px solid var(--border);
}

.inbox-reply-input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font);
  font-size: 16px; /* iOS floor */
  font-weight: 500;
  line-height: 1.4;
  color: var(--t1);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 22px;
  padding: 12px 16px;
  outline: none;
  resize: none;
}

.inbox-reply-input:focus {
  border-color: var(--blue);
}

.inbox-reply-input::placeholder {
  color: var(--t3);
}

/* the reply send button (a .btn.btn-small in markup) */
.inbox-reply .btn-small {
  flex: 0 0 auto;
  height: 48px;
  min-height: 0;
  padding: 0 16px;
  background: var(--blue);
  color: #fff;
  font-weight: 800;
  font-size: 15px;
  border-radius: var(--r-pill);
}

.inbox-reply .btn-small:active {
  background: var(--blue-press);
}

/* ==================================================================
   14. CHAT THREAD: 비서 sheet 대화 (시간순 버블)
   ================================================================== */

/* 지금 strip: head 와 quick 사이, 스크롤 안 됨. sheet 안 유일한 blue. */
.inbox-pin {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 16px 8px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-card);
  font-family: var(--font);
  text-align: left;
  cursor: pointer;
}
.inbox-pin-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--blue);
  animation: breathe 2.4s ease-in-out infinite;
}
.inbox-pin-eyebrow {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--t3);
}
.inbox-pin-text {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--t1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 날짜 구분선 */
.thread-day {
  align-self: center;
  margin: 14px auto 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--t3);
  text-align: center;
}

/* 비서 turn: 왼쪽 정렬 */
.msg-in {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  align-self: flex-start;
  max-width: 84%;
  margin: 8px 0;
}
.msg-bubble {
  background: var(--surface);
  color: var(--t1);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: -0.02em;
  padding: 10px 14px;
  border-radius: 18px 18px 18px 6px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* 시간 힌트 (recessive) */
.msg-time {
  font-size: 11px;
  color: var(--t3);
  margin: 3px 4px 0;
}
.msg-time-out {
  display: block;
  text-align: right;
  margin-top: 4px;
}

/* 로그 스탬프: 기록된 블록의 정직한 잔상 */
.msg-log {
  margin-top: 6px;
  align-self: flex-start;
  font-size: 12px;
  font-weight: 700;
  color: var(--blue);
  background: var(--blue-wash);
  border-radius: var(--r-pill);
  padding: 4px 10px;
  letter-spacing: -0.01em;
}

/* 제안 칩 행 (버블 아래, 인라인) */
.msg-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.msg-chip {
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  border: none;
  border-radius: var(--r-pill);
  padding: 7px 14px;
  cursor: pointer;
  letter-spacing: -0.01em;
}
.msg-chip-primary {
  background: var(--blue);
  color: #fff;
}
.msg-chip-primary:active {
  background: var(--blue-press);
}
.msg-chip-neutral {
  background: var(--blue-wash);
  color: var(--blue);
}
.msg-chip-decline {
  background: var(--surface);
  color: var(--t2);
  border: 1px solid var(--border);
}

/* 결정 후 한 줄 흔적 */
.msg-trace {
  margin-top: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--t3);
  letter-spacing: -0.01em;
}

/* 인라인 되돌리기 (ghost link) */
.msg-undo {
  margin-top: 6px;
  align-self: flex-start;
  font-family: var(--font);
  font-size: 12px;
  font-weight: 700;
  color: var(--t3);
  background: transparent;
  border: none;
  padding: 2px 0;
  cursor: pointer;
}
.msg-undo:active {
  color: var(--t2);
}

/* my optimistic sent line (right-aligned blue-wash bubble) */
.msg-out {
  align-self: flex-end;
  max-width: 80%;
  margin: 10px 0;
  background: var(--blue-wash);
  color: var(--blue-press);
  font-size: 15px;
  font-weight: 600;
  padding: 10px 14px;
  border-radius: 18px 18px 4px 18px;
  line-height: 1.45;
  word-break: break-word;
}

/* timestamp nested inside the user bubble */
.msg-out .msg-time-out {
  color: rgba(27, 100, 218, 0.6); /* --blue-press at lower opacity, recedes on the wash */
}

/* dark mode: user bubble text + time stay readable on the dark blue wash */
@media (prefers-color-scheme: dark) {
  .msg-out {
    color: var(--t1);
  }
  .msg-out .msg-time-out {
    color: var(--t3);
  }
}

/* assistant thinking: a quiet line with three breathing dots */
.msg-thinking {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--t3);
  font-size: 14px;
  font-weight: 600;
  padding: 8px 4px 12px;
}

.msg-thinking::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--t3);
  box-shadow: 12px 0 0 var(--t3), 24px 0 0 var(--t3);
  margin-left: 4px;
  animation: breathe 1.4s ease-in-out infinite;
}

/* live activity steps (what the assistant is doing right now). When present they stack
   vertically; the bare three-dot pulse (::after) is hidden in favor of the step list. */
.msg-thinking:has(.think-step) {
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
}
.msg-thinking:has(.think-step)::after {
  display: none;
}
.think-step {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.3;
}
.think-step::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex: none;
}
.think-step.is-done {
  color: var(--t3);
  opacity: 0.7;
}
.think-step.is-done::before {
  background: var(--green, #2ba471);
}
.think-step.is-active {
  color: var(--t2);
}
.think-step.is-active::before {
  background: var(--blue);
  animation: breathe 1.4s ease-in-out infinite;
}

/* deep-link flash: a one-shot blue-wash highlight */
.flash {
  animation: flash 900ms var(--ease);
}

@keyframes flash {
  0% {
    background: var(--blue-wash);
  }
  100% {
    background: var(--surface);
  }
}

/* empty inbox: a friendly centered line */
.inbox-empty {
  text-align: center;
  color: var(--t3);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.6;
  padding: 48px 24px;
}

/* ==================================================================
   15. SCOPE SHEET (recurring edit confirm)
   ================================================================== */

.scope-sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(15, 18, 22, 0.42);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  animation: scrim-in var(--dur) var(--ease);
}

.scope-card {
  background: var(--surface);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  box-shadow: var(--sh-sheet);
  padding: 22px 20px calc(18px + var(--safe-bottom));
  animation: sheet-pop var(--dur-slow) var(--ease);
}

.scope-msg {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--t1);
  text-align: center;
  margin-bottom: 18px;
}

.scope-actions {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

/* scope buttons are full-width comfortable sheet buttons */
.scope-btn {
  width: 100%;
  height: 54px;
  font-size: 16px;
  border-radius: var(--r-btn);
}

.scope-btn.btn-primary {
  font-weight: 800;
}

.scope-cancel {
  display: block;
  width: 100%;
  margin-top: 12px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  color: var(--t3);
  padding: 10px;
}

/* ==================================================================
   18. TOAST + LOADING + STATES
   ================================================================== */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(96px + var(--safe-bottom));
  transform: translateX(-50%);
  z-index: 70;
  max-width: calc(100vw - 40px);
  background: var(--surface);
  color: var(--t1);
  font-size: 14px;
  font-weight: 700;
  padding: 13px 20px;
  border-radius: var(--r-pill);
  box-shadow: var(--sh-sheet);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  animation: toast-in var(--dur) var(--ease);
}

.toast.is-error {
  background: var(--red);
  color: #fff;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translate(-50%, 8px);
  }
  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}

/* optional loading shimmer (available for skeleton rows) */
.skeleton {
  background: linear-gradient(100deg, #edeff2 30%, #f6f8fa 50%, #edeff2 70%);
  background-size: 200% 100%;
  animation: shimmer 1.3s linear infinite;
  border-radius: 12px;
}

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* ==================================================================
   19. WIDER SCREENS (tablet / desktop): center sheets, two-pane calendar
   ================================================================== */

@media (min-width: 720px) {
  /* center the editor and settings cards as real dialogs, not bottom sheets */
  #task-modal,
  #settings-modal {
    justify-content: center;
    align-items: center;
    padding: 24px;
  }

  #task-modal .modal-card,
  #settings-modal .modal-card {
    width: 100%;
    max-width: 520px;
    border-radius: var(--r-card);
    max-height: 88vh;
    max-height: 88dvh;
  }

  /* the inbox stays a bottom sheet but constrained to a comfortable width */
  .inbox-sheet-modal {
    align-items: center;
  }

  .inbox-card {
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    border-radius: var(--r-sheet);
  }

  .inbox-sheet-modal.is-open .inbox-card {
    transform: translateY(0);
  }

  .scope-sheet {
    justify-content: center;
    align-items: center;
    padding: 24px;
  }

  .scope-card {
    width: 100%;
    max-width: 420px;
    border-radius: var(--r-card);
  }

  /* on a wide screen there is room, so the backlog returns as a side panel beside the
     calendar (it is display:none on a phone calendar screen). */
  body:not(.view-list) main.layout {
    flex-direction: row;
  }

  body:not(.view-list) .calendar-pane {
    flex: 1 1 auto;
  }

  body:not(.view-list) .backlog-pane {
    display: block;
    flex: 0 0 360px;
    max-height: none;
    border-top: none;
    border-left: 1px solid var(--border);
  }

  .asst-bar {
    padding-left: max(24px, var(--safe-left));
    padding-right: max(24px, var(--safe-right));
  }

  .asst-bar-status,
  .asst-bar-form {
    max-width: 760px;
    margin-left: auto;
    margin-right: auto;
  }
}

/* ==================================================================
   20. REDUCED MOTION (respect prefers-reduced-motion)
   ================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ==================================================================
   21. CUSTOM SCROLLBARS (Toss-style, understated, dark-mode aware)
   ================================================================== */

/*
  커스텀 스크롤바: PC 네이티브 스크롤바 대신 토스풍의 은은한 thumb.
  저대비(--border -> hover --t3), 트랙 투명. 다크모드는 토큰이 이미
  재정의돼 있어 자동 대응. 모바일은 오버레이 스크롤바라 영향 없음.
  .calendar-allday 는 의도적으로 스크롤바를 숨기므로 제외.
*/
.calendar,
.backlog-pane,
.inbox-list,
.editor-card,
#settings-modal .modal-card,
.grow-input,
.month-grid {
  scrollbar-width: thin;                       /* Firefox */
  scrollbar-color: var(--border) transparent;  /* Firefox: thumb track */
}

.calendar::-webkit-scrollbar,
.backlog-pane::-webkit-scrollbar,
.inbox-list::-webkit-scrollbar,
.editor-card::-webkit-scrollbar,
#settings-modal .modal-card::-webkit-scrollbar,
.grow-input::-webkit-scrollbar,
.month-grid::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.calendar::-webkit-scrollbar-track,
.backlog-pane::-webkit-scrollbar-track,
.inbox-list::-webkit-scrollbar-track,
.editor-card::-webkit-scrollbar-track,
#settings-modal .modal-card::-webkit-scrollbar-track,
.grow-input::-webkit-scrollbar-track,
.month-grid::-webkit-scrollbar-track {
  background: transparent;
}

.calendar::-webkit-scrollbar-thumb,
.backlog-pane::-webkit-scrollbar-thumb,
.inbox-list::-webkit-scrollbar-thumb,
.editor-card::-webkit-scrollbar-thumb,
#settings-modal .modal-card::-webkit-scrollbar-thumb,
.grow-input::-webkit-scrollbar-thumb,
.month-grid::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 8px;
  border: 2px solid transparent;   /* inset so the thumb reads thinner */
  background-clip: padding-box;
}

.calendar::-webkit-scrollbar-thumb:hover,
.backlog-pane::-webkit-scrollbar-thumb:hover,
.inbox-list::-webkit-scrollbar-thumb:hover,
.editor-card::-webkit-scrollbar-thumb:hover,
#settings-modal .modal-card::-webkit-scrollbar-thumb:hover,
.grow-input::-webkit-scrollbar-thumb:hover,
.month-grid::-webkit-scrollbar-thumb:hover {
  background: var(--t3);
}

/* 스크롤바 화살표 버튼 제거 (위/아래 단추 없음) */
.calendar::-webkit-scrollbar-button,
.backlog-pane::-webkit-scrollbar-button,
.inbox-list::-webkit-scrollbar-button,
.editor-card::-webkit-scrollbar-button,
#settings-modal .modal-card::-webkit-scrollbar-button,
.grow-input::-webkit-scrollbar-button,
.month-grid::-webkit-scrollbar-button {
  display: none;
  width: 0;
  height: 0;
}
