/* Styles for the ToDo board. Whatever is changed in the settings drawer takes effect through CSS variables and data-* attributes
   on <html> (lib/theme.js).
   From top to bottom: colors and variables, header bar, header animation and the style slider, page layout (sections, cards),
   items and the done animation, hover tools, status pills, agent cards, buttons and inputs, popovers, settings drawer, due dates
   and calendar, recently done (bars, heatmap, two small animations), date picker, check-ins, repeat picker, agent layout, Canvas
   sync, table of contents, places; phones (below 640px) and touch screens come last so that they override everything above.
   Hover styles are all wrapped in @media (hover: hover) so they do not stick on touch screens. */
  @font-face { font-family: "Adventor Todo"; src: url("fonts/adventor-todo-regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
  @font-face { font-family: "Adventor Todo"; src: url("fonts/adventor-todo-bold.woff2") format("woff2"); font-weight: 700; font-display: swap; }
  :root {
    --background: 210 33% 99%; --foreground: 240 10% 3.9%; --card: 0 0% 100%;
    --secondary: 240 4.8% 95.9%; --muted: 240 4.8% 95%; --muted-foreground: 240 3.8% 28.1%;
    --border: 240 5.9% 88%; --faint: 240 4% 46%; --warn: 32 85% 34%; --warn-bg: 40 100% 94%;
    --font: "Adventor Todo"; --fs: 15px; --width: 1040px; --radius: 12px; --pad: 18px; --rowpad: 12px; --gap: 14px; --blockgap: 44px;
    --accent: hsl(var(--foreground)); --accent-ink: hsl(var(--background)); --hero-flag: 352 65% 43%;
  }
  html[data-mode="dark"] { --background: 240 20.54% 5.2%; --foreground: 0 0% 98%; --card: 240 10% 3.9%;
    --secondary: 240 3.7% 15.9%; --muted: 240 5.9% 12%; --muted-foreground: 240 5% 74.9%; --border: 240 3.7% 19.9%; --faint: 240 4% 58%;
    --warn: 40 95% 72%; --warn-bg: 36 40% 14%; --hero-flag: 352 80% 64%; }
  @media (prefers-color-scheme: dark) { html[data-mode="auto"] { --background: 240 20.54% 5.2%; --foreground: 0 0% 98%; --card: 240 10% 3.9%;
    --secondary: 240 3.7% 15.9%; --muted: 240 5.9% 12%; --muted-foreground: 240 5% 74.9%; --border: 240 3.7% 19.9%; --faint: 240 4% 58%;
    --warn: 40 95% 72%; --warn-bg: 36 40% 14%; --hero-flag: 352 80% 64%; } }
  /* Compact: less whitespace */
  html[data-density="compact"] { --pad: 13px; --rowpad: 7px; --gap: 10px; --blockgap: 30px; }
  /* Native controls (time inputs, dropdowns, scrollbars) follow the light/dark setting */
  html[data-mode="light"] { color-scheme: light; } html[data-mode="dark"] { color-scheme: dark; } html[data-mode="auto"] { color-scheme: light dark; }
  * { box-sizing: border-box; }
  html { -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
  /* Touch screens: a double tap does not zoom the page (pinch zoom still works), and a press shows no gray system highlight box;
     the element fades a little while held instead. While the page is locked (settings or a popover open on a phone), the page
     behind does not scroll along */
  html { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
  @media (hover: none) { button:not(:disabled):active, a:active, .seg button:active { opacity: .6; } }
  html.lock { overflow: hidden; } /* lock only html: if body also had overflow set, it would become the header bar's scroll container and the bar would jump away */
  body { margin: 0; background: hsl(var(--background)); color: hsl(var(--foreground));
    font: var(--fs)/1.7 var(--font), -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; }
  button, input, textarea, select { font: inherit; color: inherit; }
  /* The monospace font is used only where text is purely numeric (card numbers like 01, counts, times like 12:58) so that digits
     line up; small text mixing Chinese and digits uses the body font.
     Monospace fonts have no Chinese glyphs, so Chinese falls back to some other font: on macOS that is PingFang, the same as the
     body text, so it goes unnoticed; on Windows it is NSimSun, which looks different at a glance. So this monospace stack lists the
     body text's Chinese fonts before the final monospace: any Chinese that ends up here still matches the body text */
  .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", monospace; }
  main a { color: inherit; text-decoration: underline; text-decoration-color: hsl(var(--foreground) / .3); text-underline-offset: 3px; text-decoration-thickness: 1px; }
  @media (hover: hover) { main a:hover { text-decoration-color: currentColor; } }
  main code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", monospace; font-size: .88em; padding: 1px 5px; border-radius: 5px; background: hsl(var(--secondary)); }
  .container { max-width: var(--width); margin: 0 auto; padding: 0 max(32px, env(safe-area-inset-right)) 0 max(32px, env(safe-area-inset-left)); }

  /* Header bar: stays floating at the top after scrolling down. Once the page leaves the top, the bar draws in a little and gets
     shorter, turning into a frosted-glass panel with a thin border and a very faint shadow; back at the top it expands again. The
     outer element keeps its height, so the page does not jump */
  header { position: sticky; top: 0; z-index: 30; height: 80px; pointer-events: none;
    --hdr-glass: var(--background); --hdr-alpha: .94; --hdr-filter: none; --hdr-hi: .65; }
  html[data-mode="dark"] header { --hdr-glass: var(--muted); --hdr-hi: .08; }
  @media (prefers-color-scheme: dark) { html[data-mode="auto"] header { --hdr-glass: var(--muted); --hdr-hi: .08; } }
  @supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) { header { --hdr-alpha: .75; --hdr-filter: blur(16px) saturate(1.2); } }
  @media (prefers-reduced-transparency: reduce) { header { --hdr-alpha: 1; --hdr-filter: none; } }
  header .bar { position: relative; pointer-events: auto; display: flex; align-items: center; gap: 12px; height: 80px;
    border: 1px solid transparent; border-radius: 16px;
    transition: height .3s ease, padding .3s ease, margin .3s ease, transform .3s ease, border-color .15s, box-shadow .15s; }
  header .bar::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
    background-color: transparent; transition: background-color .15s; }
  header.not-top .bar { height: 56px; padding: 0 10px 0 18px; transform: translateY(10px); border-color: hsl(var(--border));
    box-shadow: inset 0 1px 0 hsl(0 0% 100% / var(--hdr-hi)), 0 0 0 1px hsl(var(--border) / .35), 0 10px 15px -3px rgb(0 0 0 / .08), 0 4px 6px -4px rgb(0 0 0 / .08); }
  header.not-top .bar::before { background-color: hsl(var(--hdr-glass) / var(--hdr-alpha)); -webkit-backdrop-filter: var(--hdr-filter); backdrop-filter: var(--hdr-filter); }
  @media (min-width: 900px) { header.not-top .bar { margin-inline: 6%; } }
  @media (prefers-reduced-motion: reduce) { header .bar, header .bar::before { transition: none; } }
  html { scroll-padding-top: 90px; }
  .brand { font-size: 1.4em; font-weight: 700; letter-spacing: .2px; }
  /* Demo site (demo/): a small tag next to the title, and a link to the repository */
  a.demo-tag { color: hsl(var(--muted-foreground)); text-decoration: none; cursor: pointer; }
  @media (hover: hover) { a.demo-tag:hover { color: hsl(var(--foreground)); border-color: hsl(var(--muted-foreground)); } }
  .demo-tag { flex: none; margin-left: 2px; padding: 1px 8px; border: 1px solid hsl(var(--border)); border-radius: 999px;
    font-size: 12px; line-height: 18px; color: hsl(var(--muted-foreground)); white-space: nowrap; cursor: default; }
  .grow { flex: 1; }
  .hdr-meta { color: hsl(var(--faint)); font-size: 13px; margin-right: 6px; }
  .tbtn { height: 34px; padding: 0 12px; border: 1px solid hsl(var(--border)); background: hsl(var(--card)); border-radius: 8px;
    cursor: pointer; font-size: 13.5px; display: inline-flex; align-items: center; gap: 6px; }
  @media (hover: hover) { .tbtn:hover { background: hsl(var(--secondary)); } }
  .tbtn.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  /* Narrow screens: button text does not wrap; the date is hidden first, and whatever still does not fit moves to a second line */
  .brand, .tbtn { white-space: nowrap; }
  /* The phone layout is all in the "phones" section at the end of the file */

  /* Header animation: the canvas fills a rounded box */
  .hero { position: relative; height: var(--hero-h, 220px); margin-top: 4px; touch-action: manipulation; border: 1px solid hsl(var(--border)); border-radius: var(--radius);
    background: hsl(var(--card)); overflow: hidden; }
  .hero canvas { display: block; width: 100%; height: 100%; animation: hero-in .5s ease both; }
  @keyframes hero-in { from { opacity: 0; } to { opacity: 1; } }
  @media (prefers-reduced-motion: reduce) { .hero canvas { animation: none; } }
  /* The slider for switching styles during layout editing (components/SlidePicker.js; one under the header animation, one under
     the "recently done" chart): a fixed-size frame in the middle, with the names sliding in from both sides */
  .slide-picker { position: relative; width: min(calc(3 * 116px), 100%); height: 38px; margin: 16px auto 0; overflow: hidden; user-select: none; outline: none; }
  .hp-frame { position: absolute; left: 50%; top: 2px; width: 116px; height: 34px; margin-left: -58px; border: 1px solid hsl(var(--border)); border-radius: 999px;
    background: hsl(var(--card)); box-shadow: 0 1px 2px hsl(240 10% 4% / .04), 0 4px 14px hsl(240 10% 4% / .05); transition: border-color .2s; }
  .slide-picker:focus-visible .hp-frame { border-color: hsl(var(--foreground) / .45); }
  .hp-item { position: absolute; left: 50%; top: 2px; width: 116px; height: 34px; margin-left: -58px; padding: 0; border: 0; background: none;
    font: inherit; font-size: 14px; line-height: 34px; text-align: center; white-space: nowrap; color: hsl(var(--foreground)); opacity: var(--op); cursor: pointer;
    transition: opacity .15s; will-change: transform; }
  .hp-item.center { cursor: default; }
  @media (hover: hover) { .hp-item:not(.center):hover { opacity: calc(var(--op) + .3); } }

  main { padding: 20px 0 120px; }
  .block { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 0 28px; margin-top: var(--blockgap); }
  .block:first-child { margin-top: 18px; }
  .block > .side { padding-top: 10px; position: relative; }
  .block > .side h2 { margin: 0; font-size: 1.33em; font-weight: 700; line-height: 1.3; }
  .block > .side .sub { margin-top: 6px; color: hsl(var(--faint)); font-size: 13px; line-height: 1.5; white-space: pre-line; }
  .stack { display: flex; flex-direction: column; gap: var(--gap); }
  /* Both columns may be narrower than their unbreakable text (on narrow screens and in the title-on-top layout, one long line
     cannot push the 1fr column off the screen) */
  .block > .stack, .block > .side { min-width: 0; }
  html[data-layout="stacked"] .block { grid-template-columns: 1fr; }
  html[data-layout="stacked"] .block > .side { padding: 0 0 12px; display: flex; align-items: baseline; gap: 12px; }
  html[data-layout="stacked"] .block > .side .sub { margin-top: 0; }
  .block.is-hidden { opacity: .5; }
  @media (max-width: 760px) { .block { grid-template-columns: 1fr; } .block > .side { padding: 0 0 12px; } }

  .card { background: hsl(var(--card)); border: 1px solid hsl(var(--border)); border-radius: var(--radius); padding: var(--pad) calc(var(--pad) + 4px); position: relative; }
  .card h3 { margin: 0; font-size: 1.13em; font-weight: 700; display: flex; align-items: baseline; gap: 10px; }
  .card h3 .no { color: hsl(var(--faint)); font-weight: 400; font-size: 14px; }
  .card h3 .count { margin-left: auto; color: hsl(var(--faint)); font-weight: 400; font-size: 13px; }
  .card .desc { margin: 6px 0 0; color: hsl(var(--muted-foreground)); font-size: .93em; line-height: 1.65; white-space: pre-line; }

  .stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap); }
  .stat { text-align: center; padding: 18px 10px 14px; }
  .stat .ic { display: flex; justify-content: center; color: hsl(var(--muted-foreground)); }
  .stat .ic .si { width: 17px; height: 17px; }
  .stat .n { font-size: 2em; font-weight: 700; line-height: 1.25; margin-top: 4px; }
  .stat .l { font-size: .93em; color: hsl(var(--muted-foreground)); }
  @media (max-width: 760px) { .stats { grid-template-columns: repeat(2, 1fr); } }

  .items { margin-top: 12px; border-top: 1px solid hsl(var(--border)); }
  .items.flush { margin-top: 0; border-top: 0; }
  .item { display: flex; gap: 14px; align-items: flex-start; padding: var(--rowpad) 0; border-bottom: 1px solid hsl(var(--border)); }
  .item:last-child { border-bottom: 0; padding-bottom: 2px; }
  .item .body { flex: 1; min-width: 0; }
  .item .t { line-height: 1.6; overflow-wrap: anywhere; }
  .item.done .t, .item.dropped .t, .item.today-done .t, .item.today-rest .t { color: hsl(var(--faint)); }
  /* Done and dropped items are both struck through; the line is thin and takes the color of the faded text */
  /* The line is a 1px background under the title, not text-decoration, so that the moment an item is done it can be drawn from
     left to right (see web/lib/motion.js) */
  .item .t { transition: color .35s ease; }
  .item .t > span { background: linear-gradient(currentColor, currentColor) no-repeat 0 var(--strike-y, 52%) / 0 1px; }
  .item.done .t > span, .item.dropped .t > span { background-size: 100% 1px; }
  /* Just done: the line is drawn across and the ✓ on the left pops; just reopened: the line retracts. Once the line is drawn, the
     row slides down (GroupCard's FLIP) */
  .item.just-closed .t > span { animation: strike-draw .42s cubic-bezier(.65, 0, .35, 1) both; }
  .item.just-opened .t > span { animation: strike-erase .3s cubic-bezier(.65, 0, .35, 1) both; }
  .item.just-closed .pill .si { animation: check-pop .5s cubic-bezier(.34, 1.56, .64, 1) both; }
  @keyframes strike-draw { from { background-size: 0 1px; } to { background-size: 100% 1px; } }
  @keyframes strike-erase { from { background-size: 100% 1px; } to { background-size: 0 1px; } }
  @keyframes check-pop { from { transform: scale(.3); opacity: 0; } to { transform: none; opacity: 1; } }
  /* The sliding row passes over the other rows: its background is opaque, so it does not blend with the rows it passes, and a
     thin top line like the dividers gives a clean edge where it covers another row. No shadow: a shadow popping up as the row
     stops would look meaningless. At the start and stop positions the thin line lies exactly on the divider of the row above, so
     it appears and disappears unnoticed */
  .item.lifted { position: relative; z-index: 2; background: hsl(var(--card)); box-shadow: 0 -1px 0 hsl(var(--border)); }
  .item.exiting, .item.folding { overflow: hidden; pointer-events: none; } /* a row that is collapsing cannot be clicked */
  /* The row jumped to from the calendar or "recently done": its background lights up, then fades (a ring of shadow in the same
     color extends the highlight a little without shifting the layout) */
  .item.located, .item.located2 { border-radius: 8px; }
  .item.located { animation: item-locate 1.8s ease-out; }
  .item.located2 { animation: item-locate2 1.8s ease-out; }
  @keyframes item-locate { 0%, 35% { background: hsl(var(--secondary)); box-shadow: 0 0 0 8px hsl(var(--secondary)); } 100% { background: transparent; box-shadow: 0 0 0 8px transparent; } }
  @keyframes item-locate2 { 0%, 35% { background: hsl(var(--secondary)); box-shadow: 0 0 0 8px hsl(var(--secondary)); } 100% { background: transparent; box-shadow: 0 0 0 8px transparent; } }
  @media (prefers-reduced-motion: reduce) {
    .item, .item .t { transition: none; }
    .item.just-closed .t > span, .item.just-opened .t > span, .item.just-closed .pill .si, .item.located, .item.located2 { animation: none; }
  }
  .item .n { color: hsl(var(--muted-foreground)); font-size: .9em; margin-top: 2px; overflow-wrap: anywhere; white-space: pre-line; }
  .item .m { color: hsl(var(--faint)); font-size: 12px; margin-top: 4px; }
  .none { color: hsl(var(--faint)); font-size: 14px; padding: 10px 0 2px; }
  /* The "N more done earlier" row in a card: a line of faint text like "+ Add" that expands and collapses the items done earlier */
  .closed-more { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; padding: 10px 0 0; color: hsl(var(--faint));
    font-size: 13.5px; cursor: pointer; }
  @media (hover: hover) { .closed-more:hover { color: hsl(var(--foreground)); } }
  .closed-more .si { width: 11px; height: 11px; }

  /* Tool buttons that appear only on hover */
  .tools { display: flex; gap: 2px; visibility: hidden; flex: none; }
  /* Phones and tablets have no hover: the ✎ to the right of an item is always shown (tapping the title does not open the editor,
     so this is the only way in); move up and move down would be too cramped, so they are left out */
  @media (hover: none) { .item .tools { visibility: visible; } .item .tools .tool[title="上移"], .item .tools .tool[title="下移"] { display: none; } }
  .tools:focus-within, html[data-editing="1"] .card > h3 .tools { visibility: visible; }
  @media (hover: hover) { .item:hover .tools, .card:hover > h3 .tools, .block .side:hover .tools { visibility: visible; } }
  .tool { border: 0; background: transparent; color: hsl(var(--faint)); cursor: pointer; padding: 1px 6px; border-radius: 6px; font-size: 13px; line-height: 1.6; }
  @media (hover: hover) { .tool:hover { background: hsl(var(--secondary)); color: hsl(var(--foreground)); } }
  .side .tools { margin-top: 8px; flex-wrap: wrap; }
  .card > h3 .tools { margin-left: 4px; }

  /* Status pills are all equally wide (enough for "done today"), with left-aligned content: the icons sit in one column, the
     labels start at the same position, and the titles line up too */
  .pill { flex: none; display: inline-flex; align-items: center; justify-content: flex-start; gap: 6px; min-width: 7.1em; height: 28px; padding: 0 10px; margin-top: -1px;
    border: 1px solid hsl(var(--border)); background: hsl(var(--card)); border-radius: 8px; font-size: 13px; cursor: pointer; white-space: nowrap; }
  @media (hover: hover) { .pill:hover { background: hsl(var(--secondary)); } }
  /* Status icons (StatusIcon): only the size varies from place to place; shape and stroke width are the same everywhere */
  .si { flex: none; display: block; width: 12px; height: 12px; }
  .pill.doing { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  .pill.agent { border-style: dashed; border-color: hsl(var(--foreground) / .55); }
  .pill.waiting { background: hsl(var(--secondary)); }
  .pill.done, .pill.dropped, .pill.todo { color: hsl(var(--muted-foreground)); }
  /* The pill to the left of a recurring item: to do today / done today / day off; items handed off to an agent get a dashed border */
  .pill.routine { color: hsl(var(--muted-foreground)); }
  .pill.routine.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  .pill.routine.rest { color: hsl(var(--faint)); }
  .pill.routine.agentish:not(.on) { border-style: dashed; border-color: hsl(var(--foreground) / .45); }
  /* With an agent, the dashed frame is an SVG over the border (AgentFrame in icons.js), so that its dashes can move: while the
     agent runs (.run) they travel slowly around the pill and the gear turns. Right after the hand-off (.handoff) the gear spins
     up and slows into its turn, a second frame whirls once around and fades, and a faint ring spreads out */
  .pill.agent, .pill.agentish { position: relative; border-color: transparent; }
  .pill .gear { display: inline-flex; flex: none; }
  .pill .ants { position: absolute; left: -1px; top: -1px; width: calc(100% + 1px); height: calc(100% + 1px); overflow: visible; fill: none; pointer-events: none; }
  .pill .ants rect { stroke: hsl(var(--foreground) / .55); stroke-width: 1; stroke-dasharray: 3 2.6; }
  .pill.agentish .ants rect { stroke: hsl(var(--foreground) / .45); }
  .pill.run .ants .a { animation: ants .9s steps(6) infinite; } /* a pixel a step: redrawing a dashed line is not free, and it moves slowly anyway */
  .pill.agent.run .gear .si { animation: gear-turn 6s linear infinite; }
  .pill.handoff .gear { animation: gear-in 1.1s cubic-bezier(.1, .75, .3, 1) backwards; }
  .pill.handoff .ants .in { stroke: hsl(var(--foreground) / .85); stroke-dasharray: 1.6 4.4; animation: ants-in 1.1s cubic-bezier(.3, .7, .4, 1) both; }
  .pill.handoff::after { content: ""; position: absolute; inset: -1px; border: 1px solid hsl(var(--foreground) / .35); border-radius: 8px; pointer-events: none;
    animation: ping .8s cubic-bezier(.2, .7, .3, 1) both; }
  @keyframes ants { to { stroke-dashoffset: -5.6; } }
  @keyframes ants-in { from { stroke-dashoffset: 0; opacity: 1; } to { stroke-dashoffset: -72; opacity: 0; } }
  @keyframes gear-turn { to { transform: rotate(360deg); } }
  @keyframes gear-in { from { transform: rotate(-330deg); } }
  @keyframes ping { to { inset: -7px; border-radius: 14px; opacity: 0; } }

  .agent .where { margin-top: 4px; color: hsl(var(--muted-foreground)); font-size: .93em; }
  .agent .when { margin-top: 6px; color: hsl(var(--faint)); font-size: 12.5px; }
  .agent .note { margin-top: 8px; font-size: .93em; color: hsl(var(--muted-foreground)); white-space: pre-line; }
  /* Done, or checked in for today: the card leaves with the completion effect (leaveCard in web/lib/fx/index.js) and cannot be
     clicked while it plays */
  .card.agent[data-leaving] { pointer-events: none; }
  /* A card for an item just handed off rises into its place */
  .card.agent.arrive { animation: card-arrive .6s cubic-bezier(.22, 1, .36, 1) backwards; }
  @keyframes card-arrive { from { opacity: 0; transform: translateY(14px) scale(.97); } }
  .stale { margin-left: 10px; padding: 1px 8px; border-radius: 6px; font-size: 12px; color: hsl(var(--warn)); background: hsl(var(--warn-bg)); }
  .row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
  .btn { height: 34px; padding: 0 14px; border: 1px solid hsl(var(--border)); background: hsl(var(--secondary)); border-radius: 8px; cursor: pointer; font-size: 14px; display: inline-flex; align-items: center; gap: 6px; }
  @media (hover: hover) { .btn:hover { background: hsl(var(--muted)); border-color: hsl(var(--foreground) / .35); } }
  .btn.dark { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  @media (hover: hover) { .btn.dark:hover { opacity: .9; } }
  .btn.danger { color: hsl(0 70% 45%); }

  .add { margin-top: 10px; }
  .addlink { border: 0; background: transparent; color: hsl(var(--faint)); cursor: pointer; padding: 4px 0; font-size: 14px; }
  @media (hover: hover) { .addlink:hover { color: hsl(var(--foreground)); } }
  .addcard { border: 1px dashed hsl(var(--border)); background: transparent; border-radius: var(--radius); padding: 12px; text-align: center; color: hsl(var(--faint)); cursor: pointer; }
  @media (hover: hover) { .addcard:hover { color: hsl(var(--foreground)); border-color: hsl(var(--foreground) / .4); } }
  .addblock { margin-top: var(--blockgap); }
  .input { width: 100%; border: 1px solid hsl(var(--border)); background: hsl(var(--background)); color: hsl(var(--foreground));
    border-radius: 8px; padding: 8px 11px; font-size: 14.5px; outline: none; }
  .input:focus { border-color: hsl(var(--foreground) / .6); }
  textarea.input { resize: vertical; min-height: 58px; max-height: 70vh; }
  .css-edit { font-size: 12.5px; }
  select.input { -webkit-appearance: none; appearance: none; cursor: pointer; padding: 8px 40px 8px 11px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%237c7c88' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 16px center; background-size: 12px 12px; }
  .form { display: flex; flex-direction: column; gap: 8px; }
  .form .row { justify-content: flex-end; margin-top: 2px; }
  .form label { font-size: 12.5px; color: hsl(var(--faint)); margin-bottom: -4px; }
  .goals { margin: 0; padding-left: 20px; }
  .goals li { color: hsl(var(--muted-foreground)); font-size: .97em; line-height: 1.9; }

  .pop { position: absolute; z-index: 50; min-width: 200px; background: hsl(var(--card)); border: 1px solid hsl(var(--border)); border-radius: 12px;
    box-shadow: 0 10px 30px hsl(240 10% 4% / .14); padding: 6px; }
  /* Motion (see Popover.js): it opens out of the element that was clicked (--ox), the menu's rows follow one after another
     (--i), another view fades in while the box morphs to its size (.morphing), and a closed popover fades out (.leaving) */
  .pop { transform-origin: var(--ox, 24px) 0; animation: pop-in .18s cubic-bezier(.2, .9, .3, 1) backwards; }
  .pop > .opt { animation: pop-row .26s cubic-bezier(.2, .9, .3, 1) backwards; animation-delay: calc(20ms + var(--i, 0) * 16ms); }
  .pop > .ask, .pop > .pk, .pop > .rp { animation: pop-view .22s cubic-bezier(.2, .9, .3, 1) .06s backwards; }
  .pop.morphing { overflow: hidden; }
  .pop.leaving { animation: pop-out .15s ease-in both; pointer-events: none; }
  @media (hover: hover) { .pop .opt.s-agent:hover .si { animation: gear-turn 2.4s linear infinite; } }
  @keyframes pop-in { from { opacity: 0; transform: translateY(-6px) scale(.96); } }
  @keyframes pop-out { to { opacity: 0; transform: translateY(-4px) scale(.98); } }
  @keyframes pop-row { from { opacity: 0; transform: translateY(-4px); } }
  @keyframes pop-view { from { opacity: 0; } }
  .pop .opt { display: flex; align-items: center; gap: 10px; width: 100%; border: 0; background: transparent; padding: 8px 10px; border-radius: 8px; cursor: pointer; font-size: 14px; text-align: left; }
  @media (hover: hover) { .pop .opt:hover { background: hsl(var(--secondary)); } }
  .pop .opt .i { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; color: hsl(var(--muted-foreground)); }
  .pop .opt .i svg { width: 14px; height: 14px; }
  .pop .opt .cur { margin-left: auto; font-size: 12px; color: hsl(var(--faint)); }
  .pop .sep { height: 1px; background: hsl(var(--border)); margin: 4px 6px; }
  .pop .ask { width: 340px; padding: 8px; display: flex; flex-direction: column; gap: 8px; }
  .pop .ask .q { font-weight: 700; font-size: 14px; }
  .pop .ask .row { justify-content: flex-end; margin-top: 2px; }

  /* Settings drawer */
  /* The settings side panel slides in from the right and slides back on a click outside it, on "Close" or on Esc; the mask fades
     in and out with it. Opening is slower and eases out to a stop; closing is quicker and speeds up on its way out */
  /* Same material as the header bar: a floating pane of frosted glass, inset a little from the window edges, with rounded
     corners, a thin border and a long, very faint shadow. The glass must not be too transparent, so that text and controls stay
     legible; the page behind is dimmed only slightly, so that appearance changes can be seen while making them */
  .drawer-mask { touch-action: none; position: fixed; inset: 0; background: hsl(240 10% 4% / .08); z-index: 60;
    opacity: 0; pointer-events: none; transition: opacity .26s ease; }
  .drawer-mask.on { opacity: 1; pointer-events: auto; transition-duration: .34s; }
  .drawer { --dg: var(--background); --dhi: .65; --dalpha: .96; --dfilter: none;
    position: fixed; top: 12px; right: max(12px, env(safe-area-inset-right)); bottom: 12px; width: min(420px, calc(100vw - 24px)); z-index: 61;
    background: hsl(var(--dg) / var(--dalpha)); -webkit-backdrop-filter: var(--dfilter); backdrop-filter: var(--dfilter);
    border: 1px solid hsl(var(--border)); border-radius: 18px;
    padding: 22px 24px 40px; overflow-y: auto; overscroll-behavior: contain; box-shadow: none;
    transform: translateX(calc(100% + 24px)); pointer-events: none; transition: transform .26s cubic-bezier(.4, 0, 1, 1), box-shadow .26s; }
  html[data-mode="dark"] .drawer { --dg: var(--muted); --dhi: .08; }
  @media (prefers-color-scheme: dark) { html[data-mode="auto"] .drawer { --dg: var(--muted); --dhi: .08; } }
  @supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) { .drawer { --dalpha: .86; --dfilter: blur(22px) saturate(1.25); } }
  @media (prefers-reduced-transparency: reduce) { .drawer { --dalpha: 1; --dfilter: none; } }
  .drawer.on { transform: none; pointer-events: auto;
    box-shadow: inset 0 1px 0 hsl(0 0% 100% / var(--dhi)), 0 0 0 1px hsl(var(--border) / .35), 0 28px 56px -18px rgb(0 0 0 / .24), 0 10px 20px -10px rgb(0 0 0 / .08);
    transition: transform .4s cubic-bezier(.22, 1, .36, 1), box-shadow .4s; }
  @media (max-width: 640px) { .drawer { top: max(8px, env(safe-area-inset-top)); right: 8px; bottom: max(8px, env(safe-area-inset-bottom)); width: calc(100vw - 16px); } }
  @media (prefers-reduced-motion: reduce) { .drawer, .drawer.on, .drawer-mask, .drawer-mask.on { transition: none; } }
  .drawer-head { display: flex; align-items: center; }
  .drawer h2 { margin: 0 0 4px; font-size: 1.25em; }
  .drawer h4 { margin: 22px 0 8px; font-size: 13px; color: hsl(var(--faint)); letter-spacing: 1px; font-weight: 700; }
  .field { display: grid; grid-template-columns: 96px 1fr; gap: 8px; align-items: center; margin: 8px 0; font-size: 14px; }
  .field > span { color: hsl(var(--muted-foreground)); }
  .seg { display: inline-flex; justify-self: start; border: 1px solid hsl(var(--border)); border-radius: 8px; overflow: hidden; }
  .seg button { border: 0; background: transparent; padding: 5px 11px; cursor: pointer; font-size: 13px; border-right: 1px solid hsl(var(--border)); }
  .seg button:last-child { border-right: 0; }
  .seg button.on { background: var(--accent); color: var(--accent-ink); }
  /* Range sliders take the accent color (black or white by default, or the one chosen) instead of the browser's default blue */
  .rangewrap input[type="range"] { accent-color: var(--accent); }
  .rangewrap { display: flex; align-items: center; gap: 10px; } .rangewrap input { flex: 1; } .rangewrap .v { width: 44px; text-align: right; color: hsl(var(--faint)); font-size: 12.5px; }
  .accents { display: flex; flex-wrap: wrap; gap: 8px 6px; align-items: center; }
  .accents .input { flex: 1 1 120px; min-width: 0; max-width: 150px; }
  .swatch { flex: none; width: 24px; height: 24px; padding: 0; border: 1px solid hsl(var(--border)); border-radius: 50%; cursor: pointer; }
  .swatch.on { outline: 2px solid hsl(var(--foreground)); outline-offset: 2px; }
  .secrow { display: flex; align-items: center; gap: 6px; padding: 6px 0; border-bottom: 1px solid hsl(var(--border)); font-size: 14px; }
  .secrow .nm { flex: 1; } .secrow.hid .nm { color: hsl(var(--faint)); text-decoration: line-through; }
  /* Dates: inline due dates, the calendar block, the date picker popover */
  .due { cursor: pointer; border-bottom: 1px dotted hsl(var(--faint) / .6); }
  @media (hover: hover) { .due:hover { color: hsl(var(--foreground)); } }
  .due .soon { margin-left: 8px; padding: 0 6px; border-radius: 5px; color: hsl(var(--warn)); background: hsl(var(--warn-bg)); }
  .duewrap { position: relative; }
  .duewrap .input { padding-right: 44px; }
  .duebtn { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); border: 0; background: transparent; color: hsl(var(--faint));
    padding: 5px 7px; border-radius: 6px; cursor: pointer; display: inline-flex; }
  @media (hover: hover) { .duebtn:hover { background: hsl(var(--secondary)); color: hsl(var(--foreground)); } }
  .cal-head { display: flex; align-items: center; gap: 4px; }
  .cal-head .ttl { font-weight: 700; font-size: 1.05em; margin-right: 8px; font-variant-numeric: tabular-nums; }
  .cal-head .sum { margin-left: auto; color: hsl(var(--faint)); font-size: 12.5px; }
  .cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; margin-top: 12px; background: hsl(var(--border));
    border: 1px solid hsl(var(--border)); border-radius: max(0px, calc(var(--radius) - 4px)); overflow: hidden; }
  .cal-dow { background: hsl(var(--card)); color: hsl(var(--faint)); font-size: 12px; padding: 6px 8px; }
  .cal-cell { background: hsl(var(--card)); min-height: 88px; padding: 6px 6px 8px; min-width: 0; }
  .cal-cell .dn { display: inline-block; min-width: 22px; height: 22px; line-height: 22px; padding: 0 4px; text-align: center; font-size: 12.5px;
    color: hsl(var(--muted-foreground)); border-radius: 999px; font-variant-numeric: tabular-nums; }
  .cal-cell.out { background: color-mix(in srgb, hsl(var(--secondary)) 55%, hsl(var(--card))); }
  .cal-cell.out .dn { color: hsl(var(--faint)); opacity: .6; }
  .cal-cell.today .dn { background: var(--accent); color: var(--accent-ink); font-weight: 700; }
  .calchip { display: flex; align-items: center; gap: 5px; width: 100%; margin-top: 3px; padding: 1px 6px; border: 0; border-radius: 6px; background: hsl(var(--secondary));
    text-align: left; font-size: 12px; line-height: 1.6; white-space: nowrap; overflow: hidden; cursor: pointer; }
  .calchip .si { width: 10px; height: 10px; }
  .calchip .tt { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* Done and dropped: faded and struck through like items (when just done, the line is drawn from left to right) */
  .calchip.closed { color: hsl(var(--faint)); }
  .calchip { transition: color .35s ease; }
  .calchip .tt { background: linear-gradient(currentColor, currentColor) no-repeat 0 var(--strike-y, 52%) / 0 1px; }
  .calchip.closed .tt { background-size: 100% 1px; }
  .calchip.just-closed .tt { animation: strike-draw .42s cubic-bezier(.65, 0, .35, 1) both; }
  @media (hover: hover) { .calchip:hover { box-shadow: inset 0 0 0 1px hsl(var(--foreground) / .3); } }
  .calchip.over { color: hsl(var(--warn)); background: hsl(var(--warn-bg)); }
  .calchip.inline { display: inline-flex; width: auto; max-width: 260px; margin: 4px 6px 0 0; vertical-align: middle; }
  .cal-more { font-size: 11.5px; color: hsl(var(--faint)); margin-top: 2px; padding-left: 6px; }
  .cal-over { margin-top: 10px; font-size: 12.5px; color: hsl(var(--muted-foreground)); }
  @media (max-width: 760px) { .cal-cell { min-height: 60px; padding: 4px; } .calchip { font-size: 11px; padding: 0 4px; } }
  @media (prefers-reduced-motion: reduce) { .calchip.just-closed .tt { animation: none; } .calchip { transition: none; } }

  /* Recently done: two weeks of bars. The 7 dark ones on the right are the last 7 days (the ones counted in the title), the 7
     light ones on the left the 7 days before, with a small gap in between; the counts sit above the bars and today's date is
     bold. The shading is fixed and only marks the two weeks: no click changes it. Below, done items are listed by day */
  .dn-bars { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)) 6px repeat(7, minmax(0, 1fr)); gap: 6px; align-items: end; margin-top: 14px; }
  .dn-bar { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 3px; height: 84px; padding: 0; border: 0;
    background: transparent; color: inherit; font: inherit; cursor: pointer; min-width: 0; }
  .dn-bar .n { font-size: 11px; line-height: 1.2; color: hsl(var(--muted-foreground)); min-height: 13px; transition: opacity .2s; }
  .dn-bar .b { width: 100%; max-width: 18px; border-radius: 3px 3px 1px 1px; background: hsl(var(--foreground) / .72);
    transition: height .5s cubic-bezier(.22, 1, .36, 1) .42s, background .15s; }
  .dn-bar .b.zero { height: 2px; border-radius: 1px; background: hsl(var(--border)); }
  .dn-bar .d { font-size: 10.5px; line-height: 1.3; color: hsl(var(--faint)); }
  .dn-bar.today .d { color: hsl(var(--foreground)); font-weight: 700; }
  .dn-bar.prev .b:not(.zero) { background: hsl(var(--foreground) / .28); }
  span.dn-bar { cursor: default; }
  @media (hover: hover) { button.dn-bar:hover .b { background: hsl(var(--foreground)); } }
  /* During the knock-over (components/done/Bars.js): the bars turn into tall thin dominoes, the counts above them fade out, and
     nothing can be clicked while they fall */
  .dn-bars.playing { pointer-events: none; }
  .dn-bars.playing .n { opacity: 0; }
  .dn-bars.playing .b { width: var(--dw) !important; max-width: none; height: var(--dh) !important; transform-origin: 100% 100%;
    transition: width .22s ease, height .22s ease, background .15s; }
  .dn-bars.playing .b.zero { background: hsl(var(--foreground) / .2); border-radius: 2px; }

  /* The small button in the chart's top-right corner plays an animation (knock-over, snake). Clicking the chart itself jumps to
     that day, so the animations start only from here */
  .egg { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 26px; height: 26px; margin: -4px -6px -4px 4px; padding: 0;
    border: 0; border-radius: 7px; background: none; color: hsl(var(--faint)); cursor: pointer; }
  .egg:disabled { cursor: default; opacity: .45; }
  .egg.on { color: hsl(var(--foreground)); opacity: 1; }
  @media (hover: hover) { .egg:not(:disabled):hover { color: hsl(var(--foreground)); background: hsl(var(--secondary)); } }
  @media (prefers-reduced-motion: reduce) { .egg { display: none; } }

  /* Heatmap (components/done/Heatmap.js): one column per week, Monday at the top; the darker a cell, the more was done that day;
     today's cell is outlined. It draws as many weeks as fit; the component measures and fills in --weeks */
  .hm-wrap { --cell: 12px; --gap: 3px; margin-top: 14px; } /* --cell is the minimum cell size, --fit the size once stretched (measured and filled in by the component) */
  .hm { display: grid; grid-template-columns: 20px repeat(var(--weeks, 26), var(--fit)); grid-template-rows: 14px repeat(7, var(--fit)); gap: var(--gap); }
  .hm-mon { grid-row: 1; font-size: 10.5px; line-height: 14px; color: hsl(var(--faint)); white-space: nowrap; }
  .hm-wd { grid-column: 1; font-size: 10px; line-height: var(--fit); color: hsl(var(--faint)); }
  .hm-cell { width: var(--fit); height: var(--fit); padding: 0; border: 0; border-radius: 3px; cursor: pointer;
    transition: border-radius .25s ease, transform .25s ease, background-color .25s ease; }
  .hm-cell:disabled { cursor: default; }
  .hm-cell.l0, .hm-legend .l0 { background: hsl(var(--foreground) / .07); }
  .hm-cell.l1, .hm-legend .l1 { background: hsl(var(--foreground) / .24); }
  .hm-cell.l2, .hm-legend .l2 { background: hsl(var(--foreground) / .44); }
  .hm-cell.l3, .hm-legend .l3 { background: hsl(var(--foreground) / .66); }
  .hm-cell.l4, .hm-legend .l4 { background: hsl(var(--foreground) / .9); }
  .hm-cell.today { box-shadow: 0 0 0 1.5px hsl(var(--card)), 0 0 0 2.5px hsl(var(--foreground)); }
  @media (hover: hover) { .hm-cell:not(:disabled):hover { box-shadow: 0 0 0 1.5px hsl(var(--card)), 0 0 0 2.5px hsl(var(--foreground) / .45); } }
  .hm-legend { display: inline-flex; align-items: center; gap: 3px; }
  .hm-legend span { margin: 0 3px; }
  .hm-legend i { width: 10px; height: 10px; border-radius: 2px; }
  .hm-score { color: hsl(var(--foreground)); }
  /* Snake: days with done items become pellets (round, bigger for more items); the snake is solid squares with a small eye on its
     head; when it crashes or has eaten everything, the snake blinks a few times */
  .hm.playing { touch-action: none; user-select: none; }
  .hm.playing .hm-cell { pointer-events: none; }
  .hm.playing .hm-cell.food { border-radius: 50%; }
  .hm.playing .hm-cell.food.l1 { transform: scale(.5); }
  .hm.playing .hm-cell.food.l2 { transform: scale(.62); }
  .hm.playing .hm-cell.food.l3 { transform: scale(.76); }
  .hm.playing .hm-cell.food.l4 { transform: scale(.9); }
  .hm.playing .hm-cell.food.bonus { transform: scale(.62); background: transparent; box-shadow: inset 0 0 0 1.5px hsl(var(--foreground) / .8); }
  .hm.playing .hm-cell.snake { background: hsl(var(--foreground)); border-radius: 3px; transition: none; }
  .hm.playing .hm-cell.head { position: relative; border-radius: 4px; }
  .hm.playing .hm-cell.head::after { content: ""; position: absolute; left: 50%; top: 50%; width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px; border-radius: 50%; background: hsl(var(--card)); }
  .hm.over .hm-cell.snake { animation: hm-blink .32s steps(1) 4; }
  @keyframes hm-blink { 50% { opacity: .15; } }
  @media (max-width: 640px) { .hm-wrap { --cell: 14px; } }
  /* The day jumped to by clicking a bar: its background lights up, then fades (a ring of shadow in the same color extends the
     highlight a little without shifting the layout) */
  .dn-day.flash { border-radius: 8px; animation: dn-flash 1.7s ease-out; }
  @keyframes dn-flash { 0%, 30% { background: hsl(var(--secondary)); box-shadow: 0 0 0 10px hsl(var(--secondary)); }
    100% { background: transparent; box-shadow: 0 0 0 10px transparent; } }
  .dn-foot { display: flex; gap: 18px; }
  .dn-day { margin-top: 18px; }
  .dn-day.folding { overflow: hidden; pointer-events: none; } /* the days collapsing after a click on "Collapse" */
  .dn-day h4 { margin: 0 0 2px; font-size: 13px; font-weight: 700; color: hsl(var(--muted-foreground)); }
  .dn-day h4 .c { margin-left: 8px; font-weight: 400; color: hsl(var(--faint)); }
  .dn-item { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px solid hsl(var(--border) / .7); cursor: pointer; font-size: .95em; }
  .dn-day h4 + .dn-item { border-top: 0; }
  .dn-item .si { color: hsl(var(--muted-foreground)); }
  .dn-item .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  @media (hover: hover) { .dn-item:hover .t { text-decoration: underline; text-decoration-color: hsl(var(--foreground) / .3); text-underline-offset: 3px; } }
  .dn-item .g { flex: none; max-width: 38%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; color: hsl(var(--faint)); }
  .dn-item .tm { flex: none; font-size: 12px; color: hsl(var(--faint)); }
  /* The item just done: once the line in its card is drawn, it drops gently into "today" from above while today's bar grows */
  .dn-item.enter { animation: dn-enter .5s cubic-bezier(.22, 1, .36, 1) .42s both; }
  @keyframes dn-enter { from { opacity: 0; transform: translateY(-8px); } }
  @media (prefers-reduced-motion: reduce) { .dn-item.enter, .dn-day.flash { animation: none; } .dn-bar .b { transition: none; } }
  .pop:has(.pk) { padding: 0; }
  .pk { width: 284px; padding: 12px 14px 10px; }
  .pk-head { display: flex; align-items: center; gap: 2px; margin-bottom: 4px; }
  .pk-head .ttl { flex: 1; padding-left: 4px; font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; }
  .pk-nav { width: 28px; height: 28px; display: grid; place-items: center; border: 0; background: transparent; border-radius: 8px;
    color: hsl(var(--muted-foreground)); cursor: pointer; }
  @media (hover: hover) { .pk-nav:hover { background: hsl(var(--secondary)); color: hsl(var(--foreground)); } }
  .pk-grid { display: grid; grid-template-columns: repeat(7, 36px); justify-content: space-between; row-gap: 2px; }
  .pk-dow { height: 28px; display: grid; place-items: center; font-size: 11.5px; color: hsl(var(--faint)); }
  .pk-day { position: relative; width: 36px; height: 36px; display: grid; place-items: center; border: 0; background: transparent;
    border-radius: 10px; font-size: 13.5px; cursor: pointer; font-variant-numeric: tabular-nums; }
  @media (hover: hover) { .pk-day:hover { background: hsl(var(--secondary)); } }
  .pk-day.out { color: hsl(var(--faint)); opacity: .5; }
  .pk-day.today { background: hsl(var(--secondary)); font-weight: 700; }
  .pk-day.sel { background: var(--accent); color: var(--accent-ink); font-weight: 700; }
  .pk-day.has::after { content: ""; position: absolute; left: 50%; bottom: 5px; width: 4px; height: 4px; margin-left: -2px; border-radius: 50%;
    background: currentColor; opacity: .4; }
  .pk-day.sel.has::after { opacity: .85; }
  .pk-foot { display: flex; align-items: center; gap: 2px; margin-top: 8px; padding-top: 8px; border-top: 1px solid hsl(var(--border)); }
  .qbtn { border: 0; background: transparent; padding: 4px 8px; border-radius: 7px; font-size: 12.5px; color: hsl(var(--muted-foreground)); cursor: pointer; }
  @media (hover: hover) { .qbtn:hover { background: hsl(var(--secondary)); color: hsl(var(--foreground)); } }
  .qbtn.dim { color: hsl(var(--faint)); }
  .pk-extra { display: flex; align-items: center; gap: 8px; margin-top: 6px; padding: 0 2px; }
  .pk-extra .lbl { font-size: 12.5px; color: hsl(var(--faint)); white-space: nowrap; }
  .pk-time { width: 76px; height: 28px; padding: 0 8px; border: 1px solid hsl(var(--border)); border-radius: 7px; background: hsl(var(--background));
    color: hsl(var(--foreground)); font-size: 13px; text-align: center; outline: none; }
  .pk-time:focus { border-color: hsl(var(--foreground) / .5); }
  /* Native time input: tabular digits, without the small clock icon on the right */
  input[type="time"].pk-time { font-variant-numeric: tabular-nums; }
  input[type="time"].pk-time::-webkit-calendar-picker-indicator { display: none; }
  .pk-toggle { height: 28px; padding: 0 11px; border: 1px solid hsl(var(--border)); border-radius: 7px; background: transparent; font-size: 12.5px;
    color: hsl(var(--muted-foreground)); cursor: pointer; }
  @media (hover: hover) { .pk-toggle:hover { border-color: hsl(var(--foreground) / .35); color: hsl(var(--foreground)); } }
  .pk-toggle.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  .pk-status { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-top: 8px; border-top: 1px solid hsl(var(--border)); }
  .pk-status .txt { flex: 1; min-width: 0; font-size: 12.5px; line-height: 1.5; color: hsl(var(--muted-foreground)); }
  .qbtn.strong { color: hsl(var(--foreground)); font-weight: 700; }
  .toast { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); background: hsl(var(--foreground)); color: hsl(var(--background));
    padding: 8px 16px; border-radius: 8px; font-size: 13.5px; opacity: 0; transition: opacity .2s; pointer-events: none; z-index: 99; }
  .toast.show { opacity: .95; }
  /* Recurring items: the badge under the item and the "done today" button */
  .rep { cursor: pointer; border-bottom: 1px dotted hsl(var(--faint) / .6); }
  @media (hover: hover) { .rep:hover { color: hsl(var(--foreground)); } }
  .rep-note { color: hsl(var(--faint)); margin-left: 10px; }
  /* Check-in table */
  .hab { display: grid; grid-template-columns: minmax(150px, 1.7fr) repeat(7, minmax(36px, 1fr)) minmax(64px, auto); align-items: stretch; margin-top: 12px; }
  .hab .hd { text-align: center; font-size: 12px; color: hsl(var(--faint)); line-height: 1.35; padding: 0 0 8px; }
  .hab .hd b { display: block; font-weight: 400; font-size: 11.5px; font-variant-numeric: tabular-nums; }
  .hab .hd.today { color: hsl(var(--foreground)); font-weight: 700; }
  .hab .hd.today b { font-weight: 700; }
  .hab .nm, .hab .c, .hab .st { border-top: 1px solid hsl(var(--border)); }
  .hab .nm { min-width: 0; padding: 9px 12px 9px 0; }
  .hab .nm .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: .95em; }
  .hab .nm .r { font-size: 12px; color: hsl(var(--faint)); }
  .hab .c { display: grid; place-items: center; min-height: 54px; }
  .hab .c.today { background: color-mix(in srgb, hsl(var(--secondary)) 70%, hsl(var(--card))); }
  .hab .st { display: flex; align-items: center; justify-content: flex-end; padding-left: 10px; font-size: 12px; color: hsl(var(--faint)); white-space: nowrap; }
  .dot { width: 28px; height: 28px; padding: 0; border-radius: 50%; display: grid; place-items: center; border: 1.5px solid hsl(var(--border)); background: transparent;
    cursor: pointer; color: hsl(var(--faint)); }
  @media (hover: hover) { .dot:hover:not(:disabled) { border-color: hsl(var(--foreground) / .5); } }
  .dot.done { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
  .dot .si { width: 13px; height: 13px; }
  .dot.miss { border-style: dashed; border-color: hsl(var(--faint) / .7); }
  .dot.future { opacity: .4; cursor: default; }
  .dot.off { border: 0; cursor: default; opacity: .6; }
  @media (max-width: 760px) { .hab { grid-template-columns: minmax(96px, 1.3fr) repeat(7, minmax(26px, 1fr)) auto; } .dot { width: 22px; height: 22px; } }
  /* Repeat picker popover */
  .pop:has(.rp) { padding: 0; }
  .rp { width: 300px; padding: 12px 14px 10px; }
  .rp-title { font-weight: 700; font-size: 14px; margin: 0 0 10px 2px; }
  .rp-presets { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
  .rp-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
  .rp-day { height: 34px; border: 1px solid hsl(var(--border)); border-radius: 9px; background: transparent; cursor: pointer; font-size: 13px; }
  @media (hover: hover) { .rp-day:hover { border-color: hsl(var(--foreground) / .35); } }
  .rp-day.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  .rp .pk-extra { margin-top: 10px; }
  /* The "repeat" field in the edit form: looks the same as the due date field above it and opens the repeat picker */
  .fieldbtn { display: flex; align-items: center; gap: 10px; text-align: left; cursor: pointer; }
  .fieldbtn > span:first-child { flex: 1; min-width: 0; }
  .input::placeholder, .fieldbtn .ph { color: hsl(var(--faint)); opacity: 1; }
  .fieldbtn .fieldicon { display: inline-flex; padding: 0 1px; color: hsl(var(--faint)); }
  @media (hover: hover) { .fieldbtn:hover .fieldicon { color: hsl(var(--foreground)); } }

  /* Agent layout: one, two or three columns, dropping a column automatically when there is not enough room. With several
     columns, the cards in a row are equally tall and their buttons sit two per row at the bottom of the card; the card being
     edited takes a whole row, so the edit form is not squeezed */
  .agent-wrap { container-type: inline-size; }
  .agent-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap); }
  .agent-grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .agent-grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  @container (max-width: 720px) { .agent-grid.cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @container (max-width: 480px) { .agent-grid.cols-2, .agent-grid.cols-3 { grid-template-columns: minmax(0, 1fr); } }
  .agent-grid > .wide { grid-column: 1 / -1; }
  .agent-grid:not(.cols-1) > .card.agent { display: flex; flex-direction: column; }
  .agent-grid:not(.cols-1) > .card.agent > .row { margin-top: auto; padding-top: 14px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
  .agent-grid:not(.cols-1) > .card.agent > .row .btn { display: flex; justify-content: center; padding: 0 6px; white-space: nowrap; }
  .agent-grid .card.agent > .row .btn.b-more { display: none; } /* the "⋯" button exists only on phones */
  .block > .side .seg { margin-top: 10px; }
  html[data-layout="stacked"] .block > .side .seg { margin-top: 0; }
  .block > .side .seg button { padding: 3px 9px; font-size: 12.5px; }

  /* Canvas sync: in the block that holds the assignments, a faint text button under the title on the left, with the status of the
     last sync below it; in settings it is a regular button */
  .csync { margin-top: 8px; }
  .csync-btn { border: 0; background: transparent; color: hsl(var(--muted-foreground)); cursor: pointer; padding: 2px 0; font-size: 13px;
    display: inline-flex; align-items: center; gap: 6px; }
  @media (hover: hover) { .csync-btn:hover { color: hsl(var(--foreground)); } }
  .csync-btn[disabled], .btn[disabled] { cursor: default; }
  .csync-st { margin-top: 2px; color: hsl(var(--faint)); font-size: 12.5px; line-height: 1.6; }
  .csync-st .warn { display: flex; align-items: center; gap: 5px; color: hsl(var(--muted-foreground)); }
  .csync-st .warn svg { flex: none; }
  .csync-field { align-items: start; }
  .csync-field > span { padding-top: 7px; }
  .csync-field .csync-st { margin-top: 6px; }
  .busy .sync-ic { animation: csync-spin 1s linear infinite; }
  @keyframes csync-spin { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) { .busy .sync-ic { animation: none; } }
  html[data-layout="stacked"] .block > .side .csync { margin-top: 0; display: flex; align-items: baseline; gap: 10px; }
  html[data-layout="stacked"] .block > .side .csync-st { margin-top: 0; display: flex; gap: 10px; }
  .item .m a.src { color: inherit; text-decoration: none; border-bottom: 1px dotted hsl(var(--faint) / .6); }
  @media (hover: hover) { .item .m a.src:hover { color: hsl(var(--foreground)); } }

  /* Table of contents on the left: shown only when the left margin is wide enough. Small, faint text; the entry for the block in
     view turns darker and bold, and a short vertical bar on the left slides along to it */
  .toc { position: fixed; top: 128px; z-index: 20; max-height: calc(100vh - 168px); overflow-y: auto; scrollbar-width: none; animation: toc-in .35s ease both; }
  .toc::-webkit-scrollbar { display: none; }
  @keyframes toc-in { from { opacity: 0; transform: translateX(-6px); } }
  .toc-list { position: relative; display: flex; flex-direction: column; padding-left: 14px; border-left: 1px solid hsl(var(--border)); }
  .toc a { display: block; padding: 5px 0; font-size: 13px; line-height: 1.45; color: hsl(var(--faint)); text-decoration: none; transition: color .15s; }
  @media (hover: hover) { .toc a:hover { color: hsl(var(--foreground)); } }
  .toc a.on { color: hsl(var(--foreground)); font-weight: 700; }
  .toc-ind { position: absolute; left: -1px; top: 0; width: 2px; border-radius: 1px; background: hsl(var(--foreground));
    transition: transform .3s cubic-bezier(.22, 1, .36, 1), height .3s cubic-bezier(.22, 1, .36, 1); }
  @media (prefers-reduced-motion: reduce) { .toc { animation: none; } .toc-ind { transition: none; } }
  @media print { .toc { display: none; } }

  /* Places where handed-off items run: the few most recently used sit in a row, and one click selects one; in settings there is
     one per line, and each can be renamed or deleted */
  .places { display: flex; flex-wrap: wrap; gap: 6px; }
  .place { border: 1px solid hsl(var(--border)); background: hsl(var(--card)); border-radius: 999px; padding: 3px 11px; font-size: 12.5px; line-height: 1.5;
    cursor: pointer; color: hsl(var(--muted-foreground)); white-space: nowrap; }
  @media (hover: hover) { .place:hover { color: hsl(var(--foreground)); border-color: hsl(var(--foreground) / .35); } }
  .place.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  /* A row of options in settings (completion effect): small rounded chips like the places above, wrapping when they do not fit */
  .chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .chip { border: 1px solid hsl(var(--border)); background: hsl(var(--card)); border-radius: 999px; padding: 3px 11px; font-size: 12.5px; line-height: 1.5;
    cursor: pointer; color: hsl(var(--muted-foreground)); white-space: nowrap; }
  @media (hover: hover) { .chip:hover { color: hsl(var(--foreground)); border-color: hsl(var(--foreground) / .35); } }
  .chip.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
  .chips-field { align-items: start; } .chips-field > span { padding-top: 3px; }

  /* Completion effects (web/lib/fx/): a canvas on top of everything (confetti, fireworks, sparks, ripple, dust) and a layer for
     copies of elements (shatter fragments, the stamp, cards turning to dust). Neither blocks clicks, and both are removed once
     the effect is over */
  .fx-canvas { position: fixed; left: 0; top: 0; width: 100vw; height: 100vh; z-index: 90; pointer-events: none; }
  .fx-layer { position: absolute; left: 0; top: 0; width: 0; height: 0; z-index: 89; pointer-events: none; }
  .fx-layer > div { will-change: transform, opacity; }
  .fx-edge { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; transition: opacity .12s; }
  .fx-crack { position: absolute; overflow: visible; fill: none; stroke-width: 1; stroke-linejoin: round; }
  .fx-stamp { position: absolute; pointer-events: none; }
  .fx-stamp text { font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", var(--font), sans-serif; }
  /* The list in settings is laid out in three columns (name, use count, delete), so the inputs on every row are equally wide */
  .placelist { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 6px 8px; align-items: center; }
  .placerow { display: contents; }
  .placerow .meta { font-size: 12px; color: hsl(var(--faint)); white-space: nowrap; text-align: right; }
  .placelist > .input { grid-column: 1 / -1; }

  /* ---------- Phones (below 640px) ----------
     Principle: more items and fewer boxes per screen. Only 14px of side margin; status pills show only their icon; every row
     always has a ✎ on the right; the header bar is a single line; popovers rise from the bottom of the screen; month calendar
     cells show only dots, with the month's items listed below; in the check-in table the name takes a full row, with the seven
     cells below it. */
  .b-more, .cal-dots, .cal-agenda, .hab .st-inline { display: none; }
  @media (max-width: 640px) {
    :root { --pad: 14px; --gap: 10px; --blockgap: 30px; }
    .container { padding: 0 max(14px, env(safe-area-inset-right)) 0 max(14px, env(safe-area-inset-left)); }
    main { padding: 10px 0 90px; }
    .block > .side { padding: 0 0 10px; }
    .block > .side h2 { font-size: 1.2em; }

    /* Header bar: one line; "edit layout" moves into settings ("done editing" appears only during layout editing) */
    header { height: 58px; }
    header .bar { height: 58px; gap: 8px; }
    header.not-top .bar { height: 50px; padding: 0 6px 0 14px; transform: translateY(6px); border-radius: 14px; }
    .brand { font-size: 1.2em; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
    .hdr-meta, header .tbtn.edit-btn:not(.on) { display: none; }
    .tbtn { height: 32px; padding: 0 11px; font-size: 13px; }
    html { scroll-padding-top: 72px; }
    .hero { height: min(var(--hero-h, 220px), 150px); }

    /* Overview: the four numbers in one row */
    .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
    .stat { padding: 10px 2px 8px; }
    .stat .ic .si { width: 14px; height: 14px; }
    .stat .n { font-size: 1.45em; margin-top: 2px; }
    .stat .l { font-size: 11.5px; white-space: nowrap; }

    /* Cards and items */
    .card h3 { font-size: 1.05em; }
    .card .desc { font-size: .9em; }
    .item { gap: 10px; }
    .pill { min-width: 0; width: 32px; padding: 0; justify-content: center; }
    .pill .lbl { display: none; }

    /* Agent cards: "checked", "done" and ⋯ (taking it back and editing are in that menu) */
    .card.agent h3 { font-size: 1.02em; line-height: 1.45; }
    .agent .where, .agent .note { font-size: .88em; }
    .agent .where { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .agent .when { font-size: 12px; }
    .agent-grid > .card.agent > .row, .agent-grid:not(.cols-1) > .card.agent > .row { display: flex; gap: 6px; margin-top: 10px; padding-top: 0; }
    .agent-grid .card.agent > .row .btn.btn { flex: 1; display: inline-flex; justify-content: center; height: 34px; padding: 0 8px; font-size: 13.5px; }
    .agent-grid .card.agent > .row .btn.b-back, .agent-grid .card.agent > .row .btn.b-edit { display: none; }
    .agent-grid .card.agent > .row .btn.b-more { flex: 0 0 44px; }

    /* Title rows of the month calendar and the check-in table: wrap when they do not fit, without text breaking one character
       per line */
    .cal-head { flex-wrap: wrap; row-gap: 4px; }
    .cal-head .ttl, .cal-head .tool, .cal-head .sum { white-space: nowrap; }

    /* Check-ins: the name (and the streak) takes a full row, and the seven cells below line up with the weekdays above */
    .hab { grid-template-columns: repeat(7, minmax(0, 1fr)); margin-top: 8px; }
    .hab .hd.blank, .hab .st { display: none; }
    .hab .nm { grid-column: 1 / -1; display: flex; align-items: baseline; gap: 8px; padding: 10px 0 2px; }
    .hab .nm .t { flex: 1; min-width: 0; }
    .hab .nm .r { flex: none; }
    .hab .nm .st-inline { display: block; flex: none; font-size: 12px; color: hsl(var(--faint)); }
    .hab .c { border-top: 0; min-height: 44px; }
    .dot { width: 30px; height: 30px; }

    /* Month calendar: cells show only dots, and the month's items are listed below */
    .cal-grid { margin-top: 10px; }
    .cal-dow { padding: 4px 0; text-align: center; }
    .cal-cell { min-height: 46px; padding: 4px 2px; text-align: center; }
    .cal-cell .calchip, .cal-cell .cal-more { display: none; }
    .cal-dots { display: flex; justify-content: center; gap: 3px; margin-top: 3px; }
    .cal-dots i { width: 5px; height: 5px; border-radius: 50%; background: hsl(var(--foreground) / .75); }
    .cal-dots i.closed { background: transparent; box-shadow: inset 0 0 0 1px hsl(var(--faint)); }
    .cal-agenda { display: block; margin-top: 4px; }
    .ag-day h4 { margin: 14px 0 2px; font-size: 12.5px; font-weight: 700; color: hsl(var(--muted-foreground)); }
    .ag-item { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 0; border: 0; border-top: 1px solid hsl(var(--border) / .7);
      background: transparent; color: inherit; font: inherit; font-size: .93em; text-align: left; cursor: pointer; }
    .ag-day h4 + .ag-item { border-top: 0; }
    .ag-item .si { color: hsl(var(--muted-foreground)); }
    .ag-item .tt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .ag-item .rel { flex: none; font-size: 12px; color: hsl(var(--faint)); }
    .ag-item.soon .rel { color: hsl(var(--warn)); }
    .ag-item.closed .tt { color: hsl(var(--faint)); background: linear-gradient(currentColor, currentColor) no-repeat 0 52% / 100% 1px; }

    /* Popovers: rise from the bottom of the screen over a light mask; tapping the mask closes them */
    .pop-mask { position: fixed; inset: 0; z-index: 49; background: hsl(240 10% 4% / .2); animation: mask-in .2s ease both; touch-action: none; }
    .pop.sheet { position: fixed; left: 0; right: 0; bottom: 0; top: auto; min-width: 0; max-height: 82vh; max-height: 82dvh; overflow-y: auto; overscroll-behavior: contain;
      transition: bottom .18s ease-out;
      border-radius: 18px 18px 0 0; border-bottom: 0; padding: 18px 12px calc(14px + env(safe-area-inset-bottom));
      box-shadow: 0 -12px 40px hsl(240 10% 4% / .18); animation: sheet-in .3s cubic-bezier(.22, 1, .36, 1) both; }
    .pop.sheet::before { content: ""; position: absolute; top: 7px; left: 50%; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: hsl(var(--border)); }
    .pop.sheet .opt { padding: 12px 12px; font-size: 15px; }
    .pop.sheet .pk, .pop.sheet .rp, .pop.sheet .ask { width: auto; max-width: 420px; margin: 0 auto; }
    .pop.sheet .pk-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
    .pop.sheet .pk-day { width: 100%; height: 42px; }

    /* Recently done: bars packed a little tighter */
    .dn-bars { gap: 3px; grid-template-columns: repeat(7, minmax(0, 1fr)) 4px repeat(7, minmax(0, 1fr)); }
    .dn-bar .d { font-size: 10px; }
    .dn-item .g { display: none; }

    /* Settings: a narrower label column (still wide enough for the "stale after" label on one line) */
    .field { grid-template-columns: 90px minmax(0, 1fr); }
    .field.accent-field { align-items: start; } .field.accent-field > span { line-height: 24px; }
    /* Places: the name and the delete button share a row; the use count and the last use go below the name */
    .placelist { grid-template-columns: minmax(0, 1fr) auto; grid-auto-flow: row dense; row-gap: 0; }
    .placerow .input { grid-column: 1; margin-top: 8px; }
    .placerow .tool { grid-column: 2; margin-top: 8px; }
    .placerow .meta { grid-column: 1 / -1; text-align: left; padding: 3px 0 0 12px; }
    .placelist > .input { margin-top: 12px; }


    /* Finger-sized targets: small buttons get an extra ring of tappable area while looking the same size */
    .item .tools .tool { padding: 8px; margin: -8px -8px -8px -4px; }
    .cal-head .tool { min-width: 36px; min-height: 34px; font-size: 15px; }
    .placerow .tool, .secrow .tool { min-width: 34px; min-height: 34px; }
    .toast { bottom: calc(20px + env(safe-area-inset-bottom)); max-width: calc(100vw - 32px); }
  }
  @keyframes sheet-in { from { transform: translateY(100%); } }
  @keyframes mask-in { from { opacity: 0; } }
  .pop.sheet.leaving { animation: sheet-out .22s cubic-bezier(.4, 0, 1, 1) both; }
  .pop-mask.leaving { animation: mask-out .22s ease both; pointer-events: none; }
  @keyframes sheet-out { to { transform: translateY(100%); } }
  @keyframes mask-out { to { opacity: 0; } }
  @media (prefers-reduced-motion: reduce) {
    .pop, .pop.sheet, .pop-mask, .pop > .opt, .pop > .ask, .pop > .pk, .pop > .rp, .card.agent.arrive,
    .pill .ants rect, .pill .gear, .pill .gear .si, .pop .opt.s-agent .si { animation: none !important; }
    .pill.handoff::after { content: none; }
  }
  /* Touch screens (phones in portrait or landscape, tablets) and narrow screens: inputs are at least 16px. Below that, iPhone
     zooms the whole page in as soon as one is tapped and does not zoom back out, and Safari keeps that zoom even after a reload.
     Placed last to override the font sizes set everywhere above */
  @media (hover: none), (pointer: coarse), (max-width: 640px) {
    .input, textarea, select, input:not([type="range"]):not([type="checkbox"]):not([type="radio"]) { font-size: 16px; }
    .pk-time { width: 92px; height: 34px; }
  }
  /* Touch screens: the move up, move down and ✎ buttons to the right of a card title normally take no space (they appear only
     during layout editing) */
  @media (hover: none) { .card > h3 .tools { display: none; } html[data-editing="1"] .card > h3 .tools { display: flex; } }
