  :root{
    --bg: #F4F8FC;
    --surface: #FFFFFF;
    --ink: #132339;
    --muted: #5B7291;
    --border: #D8E3EF;
    --accent: #2A5FBF;
    --accent-soft: #E6EEFA;
    --danger: #B2453A;
    --warn: #C4841D;
    --radius: 10px;
  }
  * { box-sizing: border-box; }
  body{
    margin:0;
    background:var(--bg);
    color:var(--ink);
    font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    line-height:1.5;
  }
  .heading{ font-family: Georgia, "Iowan Old Style", "Palatino Linotype", serif; }
  .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
  .app{ max-width: 880px; margin: 0 auto; padding: 32px 20px 60px; }

  header{ display:flex; align-items:stretch; justify-content:space-between; margin-bottom:18px; flex-wrap:wrap; gap:16px; }
  header .title-col{ display:flex; flex-direction:column; justify-content:space-between; flex:1; min-width:0; }
  header .header-sub{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; min-width:0; }
  header h1{ font-size:32px; font-weight:600; margin:0; letter-spacing:-0.01em; }
  .greeting-time{ font-family: Georgia, "Iowan Old Style", "Palatino Linotype", serif; font-size:22px; color:var(--muted); margin:0 0 4px; }
  .greeting-name-row{ display:flex; align-items:center; gap:10px; }
  .greeting-avatar{ font-size:32px; line-height:1; }
  .greeting-tagline{
    font-family: Georgia, "Iowan Old Style", "Palatino Linotype", serif; font-style:italic; font-size:14px;
    color:var(--accent); margin-top:6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;
  }
  .save-note#streak-label{ margin-left:0; white-space:nowrap; }


  .quote-strip{
    font-family: Georgia, "Iowan Old Style", "Palatino Linotype", serif; font-style:italic; font-size:13.5px;
    color:var(--ink); border-left:3px solid var(--accent); padding:8px 14px; margin-bottom:16px;
    background:var(--surface); border-radius:0 8px 8px 0; line-height:1.5;
  }
  .quote-strip .author{ display:block; margin-top:3px; font-size:11.5px; font-style:normal; color:var(--muted); }
  .icon-btn{ background:none; border:none; color:var(--muted); cursor:pointer; font-size:14px; padding:2px 4px; border-radius:4px; }
  .icon-btn:hover{ background:var(--accent-soft); color:var(--accent); }

  .mini-cal{
    width:150px; height:150px; flex-shrink:0; box-sizing:border-box;
    background:var(--surface); border:1px solid var(--border); border-radius:8px; padding:7px 9px;
    display:flex; flex-direction:column;
  }
  .mini-cal .cal-header{ text-align:center; font-size:10px; font-weight:600; margin-bottom:3px; color:var(--ink); flex-shrink:0; }
  .mini-cal .cal-grid{ flex:1; display:grid; grid-template-columns: repeat(7, 1fr); grid-template-rows: auto repeat(6, 1fr); gap:2px; }
  .mini-cal .cal-dow{ text-align:center; color:var(--muted); font-size:8px; }
  .mini-cal .cal-day{ display:flex; align-items:center; justify-content:center; border-radius:3px; color:var(--ink); font-size:9px; position:relative; }
  .mini-cal .cal-day.today{ background:var(--accent); color:#fff; font-weight:600; }
  .mini-cal .cal-day.logged::after{ content:''; position:absolute; bottom:1px; left:50%; transform:translateX(-50%); width:2px; height:2px; border-radius:50%; background:var(--accent); }
  .mini-cal .cal-day.logged.today::after{ background:#fff; }
  .mini-cal .cal-day.empty{ visibility:hidden; }

  .toolbar{ text-align:right; margin-bottom:16px; }

  nav.tabs{ display:flex; gap:4px; border-bottom:1px solid var(--border); margin-bottom:24px; }
  nav.tabs button{
    background:none; border:none; padding:10px 14px; font-size:14px; color:var(--muted);
    cursor:pointer; border-bottom:2px solid transparent; margin-bottom:-1px;
  }
  nav.tabs button.active{ color:var(--ink); border-bottom-color:var(--accent); font-weight:600; }

  section{ display:none; }
  section.active{ display:block; }

  .block-manager{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:14px; }
  .block-chip{
    display:inline-flex; align-items:center; gap:5px; background:var(--surface); border:1px solid var(--border);
    border-radius:20px; padding:4px 6px 4px 12px; font-size:12.5px;
  }
  .block-chip button{ background:none; border:none; cursor:pointer; color:var(--muted); font-size:13px; padding:2px 5px; border-radius:50%; line-height:1; }
  .block-chip button:hover{ background:var(--accent-soft); color:var(--accent); }
  .field-count{
    font-size:11px; color:var(--muted); text-align:right;
    min-height:14px; margin:2px 2px 0;
  }
  .field-count.warn{ color:var(--warn); }
  .field-count.at-limit{ color:var(--danger); }

  .modal-field-label{ display:block; font-size:12px; color:var(--muted); margin:12px 0 4px; }
  #modal-extra-input{ min-height:0; resize:none; overflow:hidden; }
  /* The category's default label, shown after its name in the chip. */
  .cat-default{ color:var(--muted); font-style:italic; }

  /* ---------------------------------------------------------------
     Quarterly goals — a title, an optional note, an urgent flag.
  --------------------------------------------------------------- */
  .goals-quarter-field{
    width:100%; font-size:14px; font-weight:600; padding:6px 8px; margin-bottom:4px;
    border:1px solid var(--border); border-radius:6px; background:var(--bg); color:var(--ink);
  }
  .goals-range-hint{ font-size:11px; color:var(--muted); margin:0 0 10px; }

  .goal-item{ padding:5px 0; }
  .goal-head{ display:flex; align-items:baseline; gap:8px; cursor:pointer; }
  .goal-title{ font-size:13.5px; }
  .goal-item.done .goal-title{ color:var(--muted); text-decoration:line-through; }
  /* The commitment level. Loud at the top of the list, quiet at the
     bottom — a goal filed under "in my dreams" should not shout. */
  .goal-flag{
    font-size:10px; text-transform:uppercase; letter-spacing:.04em; font-weight:700;
    border:1px solid currentColor; border-radius:4px; padding:0 4px; flex-shrink:0; white-space:nowrap;
  }
  .goal-flag.lvl-must{ color:var(--danger); }
  .goal-flag.lvl-best{ color:var(--accent); }
  .goal-flag.lvl-dream{ color:var(--muted); font-weight:500; font-style:italic; text-transform:none; letter-spacing:0; }
  /* Indented to the title, clear of the checkbox. Wraps on its own and
     keeps any line breaks that were typed into it. */
  .goal-note{
    margin:2px 0 0 26px; font-size:12px; color:var(--muted); line-height:1.5; white-space:pre-wrap;
  }

  .goal-row{ border:1px solid var(--border); border-radius:8px; padding:8px; margin-bottom:8px; background:var(--bg); }
  .goal-row-top{ display:flex; align-items:center; gap:6px; }
  .goal-title-input{
    flex:1; min-width:0; font:inherit; font-size:13.5px; padding:5px 7px;
    border:1px solid var(--border); border-radius:6px; background:var(--surface); color:var(--ink);
  }
  .goal-note-input{ margin-top:6px; font-size:12px; min-height:0; resize:none; }
  .goal-row-top .dd{ flex-shrink:0; }
  .goals-head-right{ display:flex; align-items:center; gap:8px; flex-shrink:0; }
  .goals-banner{
    display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;
    background:var(--surface); border:1px solid var(--accent); border-radius:8px;
    padding:8px 10px; margin-bottom:12px; font-size:12.5px;
  }
  .goals-banner.archived{ border-color:var(--muted); color:var(--muted); font-style:italic; }
  .plain-btn.small{ padding:5px 10px; font-size:12px; font-style:normal; }

  /* Goals on the stats tab. */
  .card-sub{ font-weight:400; color:var(--muted); font-size:12px; }
  .goal-stat-head{ display:flex; align-items:baseline; gap:6px; margin:12px 0 10px; }
  .goal-stat-count{ font-size:28px; font-weight:600; color:var(--accent); line-height:1; }
  .goal-stat-count .of{ font-size:16px; font-weight:400; color:var(--muted); }
  .goal-stat-word{ font-size:13px; color:var(--muted); }
  .goal-stat-levels{ display:flex; flex-wrap:wrap; gap:14px; margin-bottom:14px; }
  .goal-stat-level{ display:flex; align-items:center; gap:6px; }
  .goal-stat-ratio{ font-size:12.5px; color:var(--muted); }
  .goal-timeline{ border-top:1px solid var(--border); padding-top:10px; }
  .goal-tl-row{ display:flex; gap:12px; align-items:baseline; padding:4px 0; font-size:13px; }
  .goal-tl-date{ flex-shrink:0; width:54px; color:var(--muted); font-size:12px; font-variant-numeric:tabular-nums; }
  .goal-tl-date.undated{ font-style:italic; }
  .goal-tl-title{ min-width:0; overflow-wrap:anywhere; }
  .goal-remove{
    flex-shrink:0; background:none; border:none; cursor:pointer; color:var(--muted);
    font-size:15px; padding:2px 6px; border-radius:50%; line-height:1;
  }
  .goal-remove:hover{ background:var(--accent-soft); color:var(--danger); }
  /* The category's default label. Sits inside the chip so it reads as
     part of the category rather than a separate setting. */
  .cat-default{
    width:104px; border:none; border-bottom:1px dashed var(--border); background:none;
    font:inherit; font-size:12px; color:var(--ink); padding:1px 2px; outline:none;
  }
  .cat-default::placeholder{ color:var(--muted); opacity:.7; font-style:italic; }
  .cat-default:hover{ border-bottom-color:var(--muted); }
  .cat-default:focus{ border-bottom-color:var(--accent); border-bottom-style:solid; }
  .add-block-btn{
    background:var(--surface); border:1px dashed var(--border); color:var(--muted); border-radius:20px;
    padding:5px 14px; font-size:12.5px; cursor:pointer;
  }
  .add-block-btn:hover{ border-color:var(--accent); color:var(--accent); }
  .time-fields{ display:inline-flex; align-items:center; gap:3px; }

  .grid-wrap{ overflow-x:auto; }
  /* Fixed layout: the seven day columns share the width equally. With
     the default auto layout, one long label stretched its own column
     and squeezed the other six until short words broke mid-way. */
  table.grid{ border-collapse:collapse; width:100%; min-width:760px; table-layout:fixed; }
  table.grid th{ font-size:12px; color:var(--muted); font-weight:500; text-align:center; padding:6px 4px; }
  table.grid td.rowlabel{
    font-size:12px; color:var(--muted); white-space:nowrap; padding-right:8px; text-align:right;
    font-family: Georgia, serif; font-style: italic;
  }
  table.grid td.cell{ padding:3px; vertical-align:top; }
  .block{ border-radius:8px; padding:8px 8px 7px; min-height:52px; cursor:pointer; border:1px solid transparent; transition: border-color .15s; }
  .block:hover{ border-color: var(--border); }
  /* Labels wrap at spaces on their own. `overflow-wrap:anywhere` covers
     the other case: one long unbroken string would otherwise push the
     column wider and skew the whole grid. */
  .block .cat-label, .block .free-text{ overflow-wrap:anywhere; }
  .block .cat-label{ font-size:12.5px; font-weight:600; line-height:1.3; }
  /* pre-wrap so a line break the user typed is shown where they put it. */
  .block .free-text{ font-size:11.5px; opacity:.85; margin-top:2px; line-height:1.35; white-space:pre-wrap; }
  .block .duration-label{ font-size:10px; font-weight:600; display:inline-block; padding:1px 7px; border-radius:9px; }
  /* Bottom row of a slot: duration on the left, tick box on the right,
     sharing one line instead of stacking. */
  .block-foot{ display:flex; align-items:center; gap:6px; margin-top:4px; min-height:17px; }
  .block-foot .cell-check{ margin-left:auto; }
  .block.urgent{ border:2px solid var(--danger); }
  .block.urgent .cat-label{ font-size:14.5px; font-weight:700; }
  .block.urgent .free-text{ font-size:12.5px; font-weight:600; color:var(--danger); }

  /* The editor sits inside its cell. Its column is widened while it is
     open (see the colgroup in renderGrid), so it needs no overlap. */
  .editor{
    background:var(--surface); border:1px solid var(--border); border-radius:8px; padding:8px;
    box-shadow:0 4px 14px rgba(19,35,57,.10);
  }
  /* The label field is a textarea, not an input: a single-line input
     scrolls sideways and hides everything past the right edge.
     Scoped to a direct child so it cannot catch the duration field
     nested inside the stepper. */
  .editor > textarea{
    display:block; width:100%; font-family:inherit; font-size:12px; padding:5px 6px; margin-bottom:6px;
    border:1px solid var(--border); border-radius:6px; background:var(--bg); color:var(--ink);
    line-height:1.4; overflow-wrap:anywhere;
    /* One line until there is a second one, like every other field.
       autoGrow sets the height from the content, so the floor here is
       only what an unmeasured box falls back to. */
    min-height:0; max-height:160px; overflow-y:auto; resize:none;
  }
  /* The custom dropdowns are divs, so they never picked up the spacing
     the old <select> elements had. */
  .editor > .dd{ display:block; margin-bottom:6px; }
  /* Actions are separated from the fields, so Save is not sitting flush
     against the last control. */
  /* Save and Cancel sit at the right edge, where the eye ends up after
     reading the fields. Save leads, since it is the one being aimed for. */
  .editor .row{
    display:flex; gap:6px; justify-content:flex-end; margin-top:10px; padding-top:9px;
    border-top:1px solid var(--border);
  }
  .editor button{ font-size:12px; padding:5px 10px; border-radius:6px; border:1px solid var(--border); background:var(--surface); cursor:pointer; }
  .editor button.primary{ background:var(--accent); color:#fff; border-color:var(--accent); }

  .card{ background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:18px 20px; margin-bottom:16px; }
  #goals-card{ background:var(--accent-soft); border:1px solid var(--accent); border-left:4px solid var(--accent); }
  .card h2{ font-size:15px; margin:0; font-weight:600; }
  label.log-block-row{ display:flex; align-items:center; gap:10px; padding:6px 0; font-size:14px; cursor:pointer; }
  /* The checklist has a full row of width, so a long label wraps rather
     than being cut off — the swatch and box stay put. */
  .log-block-row > span:not(.swatch):not(.opt-tag){ overflow-wrap:anywhere; min-width:0; }
  .log-block-row .swatch{ width:8px; height:8px; border-radius:2px; flex-shrink:0; }
  .rushed-row{ display:flex; align-items:center; gap:8px; margin-top:10px; padding-top:10px; border-top:1px solid var(--border); font-size:14px; }
  textarea{
    width:100%; margin-top:10px; padding:9px 10px; border-radius:8px; border:1px solid var(--border);
    background:var(--bg); color:var(--ink); font-family:inherit; font-size:13px; resize:vertical; min-height:60px;
  }
  /* Adding stays on the left, where a list grows from; saving and
     leaving go to the right, together. */
  .form-actions{ display:flex; align-items:center; gap:6px; margin-top:10px; }
  .form-actions .add-block-btn{ margin-right:auto; }
  .form-actions .save-btn{ margin-top:0; }
  .plain-btn{
    padding:9px 16px; border-radius:8px; border:1px solid var(--border);
    background:var(--surface); color:var(--ink); cursor:pointer; font-size:13px;
  }
  .plain-btn:hover{ border-color:var(--accent); color:var(--accent); }

  .save-btn{ margin-top:12px; background:var(--accent); color:#fff; border:none; padding:9px 16px; border-radius:8px; font-size:13px; cursor:pointer; font-weight:500; }
  .save-btn:hover{ opacity:.92; }
  .save-note{ font-size:12px; color:var(--muted); margin-left:10px; }

  .history-row{
    display:flex; justify-content:space-between; align-items:baseline; gap:10px; width:100%;
    font-family:inherit; font-size:13px; text-align:left; padding:7px 4px; margin:0 -4px;
    border:none; border-bottom:1px solid var(--border); border-radius:5px;
    background:none; color:var(--ink); cursor:pointer;
  }
  .history-row:hover{ background:var(--accent-soft); }
  .history-row.current{ background:var(--accent-soft); font-weight:600; }
  .history-row:last-child{ border-bottom:none; }
  .history-row .d{ color:var(--muted); font-family: ui-monospace, monospace; font-size:12px; width:90px; flex-shrink:0; }
  .history-row .note{ color:var(--muted); font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

  .stat-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap:12px; margin-bottom:16px; }
  .stat-card{ background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:14px 16px; }
  .stat-card .num{ font-size:26px; font-weight:600; font-family: ui-monospace, monospace; }
  .stat-card .lbl{ font-size:12px; color:var(--muted); margin-top:2px; }

  .catbar-row{ display:flex; align-items:center; gap:10px; font-size:13px; padding:6px 0; }
  .catbar-row .name{ width:150px; flex-shrink:0; }
  .catbar-track{ flex:1; background:var(--accent-soft); border-radius:4px; height:8px; overflow:hidden; }
  .catbar-fill{ height:100%; border-radius:4px; }
  .catbar-pct{ width:36px; text-align:right; font-family: ui-monospace, monospace; font-size:12px; color:var(--muted); }

  /* Fixed-size squares. With 1fr columns each cell stretched to ~130px
     on a wide screen, which read as an empty table rather than a
     density plot. */
  .heat-wrap{ display:flex; gap:8px; align-items:flex-start; margin-top:12px; --heat-cell:15px; --heat-gap:4px; }
  .heat-labels{ display:flex; flex-direction:column; }
  .heat-days{
    display:grid; grid-auto-rows:var(--heat-cell); gap:var(--heat-gap);
    font-size:9px; color:var(--muted); text-align:right; padding-top:1px;
  }
  .heat-days span{ line-height:var(--heat-cell); }
  .heat-strip-label{ font-size:9px; color:var(--muted); text-align:right; margin-top:14px; line-height:30px; }
  .heat-cols{ display:flex; flex-direction:column; }
  .heatmap{
    display:grid; grid-template-columns:repeat(12, var(--heat-cell));
    grid-auto-rows:var(--heat-cell); gap:var(--heat-gap);
  }
  .heatmap .cell{
    width:var(--heat-cell); height:var(--heat-cell); padding:0;
    border:1px solid transparent; border-radius:3px; background:var(--accent-soft); cursor:pointer;
  }
  .heatmap .cell:hover{ border-color:var(--accent); }
  .heatmap .cell.is-today{ box-shadow:0 0 0 1.5px var(--muted); }
  .heatmap .cell.selected{ border-color:var(--ink); }
  .heatmap .cell.empty{ background:transparent !important; border:none; cursor:default; }

  .heat-detail{ margin-top:14px; font-size:13px; }
  .heat-detail.open{ border-top:1px solid var(--border); padding-top:12px; }
  .heat-detail-head{ display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; margin-bottom:8px; color:var(--muted); font-size:12px; }
  .heat-detail-head strong{ color:var(--ink); font-size:13.5px; }
  .heat-detail-head .link-btn{ margin-left:auto; }
  .heat-block{ display:flex; align-items:center; gap:8px; padding:3px 0; color:var(--muted); }
  .heat-block.done{ color:var(--ink); }
  .heat-mark{ width:12px; text-align:center; color:var(--muted); }
  .heat-block.done .heat-mark{ color:var(--accent); font-weight:600; }
  .heat-block .swatch{ width:8px; height:8px; border-radius:2px; flex-shrink:0; }
  .heat-note{
    margin-top:8px; padding:8px 11px; background:var(--bg); border-radius:8px;
    font-size:12.5px; font-style:italic; color:var(--muted); line-height:1.5;
  }

  .footer-actions{ margin-top:20px; text-align:right; }
  .link-btn{ background:none; border:none; color:var(--muted); font-size:12px; cursor:pointer; text-decoration:underline; }

  .empty{ color:var(--muted); font-size:13px; padding:8px 0; }

  .modal-overlay{ display:none; position:fixed; inset:0; background:rgba(19,35,57,0.45); align-items:center; justify-content:center; z-index:60; padding:20px; }
  .modal-card{ background:var(--surface); border-radius:16px; padding:26px 24px; max-width:380px; width:100%; }
  .modal-card input[type=text]{
    width:100%; padding:9px 10px; border-radius:8px; border:1px solid var(--border);
    background:var(--bg); color:var(--ink); font-size:14px; margin-bottom:8px;
  }
  #avatar-grid{ display:grid; grid-template-columns: repeat(7, 1fr); gap:6px; margin-bottom:14px; }
  .avatar-btn{ font-size:20px; padding:6px 0; border-radius:8px; border:1px solid var(--border); background:var(--surface); cursor:pointer; }
  .avatar-btn.selected{ border-color:var(--accent); background:var(--accent-soft); }

  /* --- Small-screen notice ------------------------------------
     The grid is a 7-column table with a 700px minimum, so phones
     get a warning rather than a broken layout. Shown by JS only
     below 760px; dismissable for anyone who wants to look anyway. */
  #small-screen-notice{
    display:none; background:var(--accent-soft); border-bottom:1px solid var(--accent);
    padding:14px 18px; font-size:13px; color:var(--ink); line-height:1.55;
  }
  #small-screen-notice.visible{ display:block; }
  #small-screen-notice strong{ display:block; font-size:14px; margin-bottom:2px; }
  #small-screen-notice button{
    margin-top:10px; background:var(--surface); border:1px solid var(--accent); color:var(--accent);
    border-radius:8px; padding:6px 14px; font-size:12.5px; cursor:pointer;
  }

  /* =============================================================
     In-page form controls.

     Everything below exists so the app never opens a widget drawn
     by the browser or the OS: no <select> popups, no number-input
     spinners, no colour dialog, no default checkboxes.
     ============================================================= */

  /* --- Checkbox --------------------------------------------- */
  input[type=checkbox]{
    appearance:none; -webkit-appearance:none; margin:0; flex-shrink:0;
    width:16px; height:16px; border:1.5px solid var(--border); border-radius:4px;
    background:var(--surface); cursor:pointer; position:relative; transition:background .12s, border-color .12s;
  }
  input[type=checkbox]:hover{ border-color:var(--accent); }
  input[type=checkbox]:checked{ background:var(--accent); border-color:var(--accent); }
  input[type=checkbox]:checked::after{
    content:''; position:absolute; left:4.5px; top:1px; width:4px; height:8px;
    border:solid #fff; border-width:0 2px 2px 0; transform:rotate(42deg);
  }
  input[type=checkbox]:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

  /* --- Dropdown (replaces <select>) --------------------------- */
  .dd{ position:relative; display:inline-block; vertical-align:middle; }
  .dd-trigger{
    width:100%; display:flex; align-items:center; justify-content:space-between; gap:6px;
    font-family:inherit; font-size:12px; padding:5px 7px; cursor:pointer;
    border:1px solid var(--border); border-radius:6px; background:var(--bg); color:var(--ink);
    text-align:left; line-height:1.3;
  }
  .dd-trigger:hover{ border-color:var(--accent); }
  .dd.open .dd-trigger{ border-color:var(--accent); }
  .dd-label{ display:flex; align-items:center; gap:6px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .dd-caret{ color:var(--muted); font-size:9px; flex-shrink:0; }
  .dd.open .dd-caret{ transform:rotate(180deg); }
  .dd-swatch{ width:8px; height:8px; border-radius:2px; flex-shrink:0; }
  .dd-menu{
    display:none; position:absolute; top:calc(100% + 3px); left:0; z-index:40;
    min-width:100%; max-height:min(55vh, 264px); overflow-y:auto; padding:4px;
    background:var(--surface); border:1px solid var(--border); border-radius:8px;
    box-shadow:0 6px 18px rgba(19,35,57,.13);
  }
  .dd-menu-right{ left:auto; right:0; }
  /* The quarter list gets its own ceiling: one year — a heading and its
     four quarters — plus a sliver of the next heading, so it reads as
     "there is more below". Set here rather than on .dd-menu because the
     category dropdown shares that rule and is picked from constantly
     while editing a slot; four rows there would mean scrolling to reach
     a category you use every day. Sized from the measured row heights
     (25px heading, 26px option, 8px padding). */
  #dd-quarter-pick .dd-menu{ max-height:min(45vh, 149px); }

  /* Sticks to the top of the menu while scrolling, so you always know
     which year you are looking at. */
  .dd-header{
    position:sticky; top:-4px; z-index:1; background:var(--surface);
    padding:6px 8px 3px; font-size:10.5px; font-weight:700; letter-spacing:.06em;
    text-transform:uppercase; color:var(--muted);
  }
  .dd.open .dd-menu{ display:block; }
  .dd-option{
    width:100%; display:flex; align-items:center; gap:7px; white-space:nowrap;
    font-family:inherit; font-size:12px; text-align:left; padding:6px 8px;
    border:none; border-radius:5px; background:none; color:var(--ink); cursor:pointer;
  }
  .dd-option:hover{ background:var(--accent-soft); }
  .dd-option.selected{ background:var(--accent-soft); color:var(--accent); font-weight:600; }

  /* --- Stepper (replaces <input type=number>) ----------------- */
  .stepper{
    display:flex; align-items:stretch;
    border:1px solid var(--border); border-radius:6px; background:var(--bg); overflow:hidden;
  }
  .stepper:focus-within{ border-color:var(--accent); }
  .stepper input{
    flex:1; min-width:0; width:100%; margin:0 !important; border:none !important;
    background:none !important; text-align:center; font-family:inherit; font-size:12px;
    padding:5px 2px !important; color:var(--ink); outline:none;
  }
  .stepper-btn{
    width:24px; flex-shrink:0; border:none; background:none; cursor:pointer;
    color:var(--muted); font-size:14px; line-height:1; padding:0;
  }
  .stepper-btn:hover{ background:var(--accent-soft); color:var(--accent); }

  /* --- Colour palette (replaces <input type=color>) ----------- */
  .cp{ position:relative; display:inline-flex; }
  .cp-trigger{
    width:11px; height:11px; padding:0; border:none; border-radius:3px; cursor:pointer;
  }
  .cp-trigger:hover{ box-shadow:0 0 0 2px var(--accent-soft); }
  .cp-menu{
    display:none; position:absolute; top:calc(100% + 6px); left:-6px; z-index:40;
    grid-template-columns:repeat(6, 1fr); gap:6px; padding:8px;
    background:var(--surface); border:1px solid var(--border); border-radius:10px;
    box-shadow:0 6px 18px rgba(19,35,57,.13);
  }
  .cp.open .cp-menu{ display:grid; }
  .cp-swatch{
    width:20px; height:20px; padding:0; border:2px solid transparent; border-radius:5px; cursor:pointer;
  }
  .cp-swatch:hover{ transform:scale(1.12); }
  .cp-swatch.selected{ border-color:var(--ink); }

  /* --- Textarea: the drag handle is drawn by the browser ------ */
  textarea{ resize:none; }
  #goals-text-input{ min-height:110px; }

  /* --- Scrollbars --------------------------------------------- */
  .dd-menu::-webkit-scrollbar, .grid-wrap::-webkit-scrollbar{ height:8px; width:8px; }
  .dd-menu::-webkit-scrollbar-thumb, .grid-wrap::-webkit-scrollbar-thumb{
    background:var(--border); border-radius:4px;
  }
  .dd-menu::-webkit-scrollbar-thumb:hover, .grid-wrap::-webkit-scrollbar-thumb:hover{ background:var(--muted); }
  .dd-menu::-webkit-scrollbar-track, .grid-wrap::-webkit-scrollbar-track{ background:transparent; }

  /* --- Collapsible card section -------------------------------- */
  .card-toggle{
    width:100%; display:flex; align-items:center; justify-content:space-between; gap:12px;
    background:none; border:none; padding:0; cursor:pointer; font-family:inherit; color:inherit; text-align:left;
  }
  .card-toggle h2{ margin:0; }
  .card-toggle-meta{ display:flex; align-items:center; gap:10px; font-size:12px; color:var(--muted); }
  .card-toggle .chev{ font-size:11px; transition:transform .18s; }
  .card-toggle .chev.up{ transform:rotate(180deg); }
  .card-toggle:hover .card-toggle-meta{ color:var(--accent); }

  .collapsible{ display:none; }
  .collapsible.open{ display:block; animation:reveal .18s ease-out; }
  @keyframes reveal{ from{ opacity:0; transform:translateY(-3px); } to{ opacity:1; transform:none; } }
  @media (prefers-reduced-motion: reduce){
    .collapsible.open{ animation:none; }
    .card-toggle .chev{ transition:none; }
  }

  .caption{ font-size:12.5px; color:var(--muted); line-height:1.55; margin:12px 0 0; max-width:62ch; }

  .heat-legend{
    display:flex; align-items:center; gap:5px; margin-top:12px; font-size:11px; color:var(--muted);
  }
  .heat-legend .lg{ width:12px; height:12px; border-radius:3px; }
  .heat-legend span:last-child{ margin-left:3px; }

  /* --- Log tab: day header and actions ------------------------ */
  .log-head{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
  .log-actions{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
  .log-actions .save-btn{ margin-top:0; }
  .log-actions .save-note{ margin-left:0; }
  .log-actions .save-note .link-btn{ margin-left:4px; }

  /* --- Header picture ------------------------------------------
     Height is fixed so switching aspect ratio changes the width, not
     the height of the whole header — the page doesn't jump. */
  .header-media{ display:flex; flex-direction:column; align-items:flex-end; gap:6px; flex-shrink:0; }
  .media-frame{
    height:150px; width:auto; max-width:100%; position:relative; overflow:hidden;
    border-radius:10px; background:var(--surface); border:1px solid var(--border);
  }
  .media-frame img{ width:100%; height:100%; object-fit:cover; display:block; }
  .media-frame.empty{
    display:flex; align-items:center; justify-content:center; cursor:pointer;
    border:1px dashed var(--border); min-width:90px;
  }
  .media-frame.empty:hover{ border-color:var(--accent); }
  .media-frame.dropping{ border-color:var(--accent); background:var(--accent-soft); }
  .media-hint{
    display:flex; flex-direction:column; align-items:center; gap:2px;
    font-size:12px; color:var(--muted); text-align:center; padding:0 10px;
  }
  .media-hint small{ font-size:10.5px; opacity:.75; }

  .media-actions{
    position:absolute; inset:auto 0 0 0; display:flex; gap:4px; justify-content:flex-end;
    padding:6px; opacity:0; transition:opacity .15s;
    background:linear-gradient(transparent, rgba(19,35,57,.62));
  }
  .media-frame:hover .media-actions, .media-frame:focus-within .media-actions{ opacity:1; }
  .media-actions button{
    width:22px; height:22px; flex-shrink:0; padding:0; line-height:1;
    border:none; border-radius:5px; font-size:12px; font-family:inherit;
    background:rgba(255,255,255,.92); color:var(--ink); cursor:pointer;
  }
  .media-actions button:hover{ background:#fff; }

  /* .ratio-chip is now used only inside the cropper. */
  .ratio-chip{
    border:1px solid var(--border); background:var(--surface); color:var(--muted);
    border-radius:20px; padding:2px 9px; font-size:10.5px; font-family:inherit; cursor:pointer;
  }
  .ratio-chip:hover{ border-color:var(--accent); color:var(--accent); }
  .ratio-chip.selected{ border-color:var(--accent); background:var(--accent-soft); color:var(--accent); font-weight:600; }

  .export-icon-btn{ font-size:15px; padding:4px 8px; border-radius:6px; }

  @media (max-width: 760px){
    .header-media{ align-items:flex-start; }
  }

  /* --- Week totals, aligned under the heatmap columns ----------- */
  .week-strip{
    display:grid; grid-template-columns:repeat(12, var(--heat-cell)); gap:var(--heat-gap);
    margin-top:10px; padding-top:8px; border-top:1px solid var(--border);
  }
  .week-strip .wbar{
    width:var(--heat-cell); height:30px; padding:0; border:none; background:none;
    display:flex; align-items:flex-end; cursor:pointer; border-radius:3px;
  }
  .week-strip .wbar span{ width:100%; background:var(--accent); border-radius:2px 2px 0 0; display:block; }
  .week-strip .wbar.empty span{ background:var(--border); }
  .week-strip .wbar:hover span{ opacity:.75; }
  .week-strip .wbar.selected span{ background:var(--ink); }

  .heat-week-figure{
    font-size:26px; font-weight:600; font-family:ui-monospace, monospace;
    color:var(--ink); line-height:1.2;
  }

  /* --- Heatmap window navigation -------------------------------- */
  .heat-nav{ display:flex; align-items:center; gap:10px; margin-top:14px; }
  .heat-nav span{ font-size:12px; color:var(--ink); font-family:ui-monospace, monospace; }
  .heat-nav button{
    width:24px; height:24px; padding:0; line-height:1; font-size:12px; font-family:inherit;
    border:1px solid var(--border); border-radius:6px; background:var(--surface);
    color:var(--muted); cursor:pointer;
  }
  .heat-nav button:hover:not(:disabled){ border-color:var(--accent); color:var(--accent); }
  .heat-nav button:disabled{ opacity:.35; cursor:default; }

  /* --- Cropper -------------------------------------------------- */
  .crop-card{ max-width:420px; }
  .crop-ratios{ display:flex; gap:5px; flex-wrap:wrap; margin-bottom:12px; }
  .crop-stage{
    position:relative; overflow:hidden; margin:0 auto;
    border-radius:10px; background:var(--ink); cursor:grab; touch-action:none;
    box-shadow:0 0 0 1px var(--border);
  }
  .crop-stage:active{ cursor:grabbing; }
  .crop-stage img{ position:absolute; user-select:none; -webkit-user-drag:none; max-width:none; }
  .crop-zoom{
    display:flex; align-items:center; justify-content:center; gap:8px;
    margin-top:12px; font-size:12px; color:var(--muted);
  }
  .crop-zoom .stepper-btn{
    width:26px; height:26px; border:1px solid var(--border); border-radius:6px; background:var(--surface);
  }
  .crop-zoom-value{ font-family:ui-monospace, monospace; width:42px; text-align:center; color:var(--ink); }

  /* A slot with nothing planned: visible as a target, but not a plan. */
  .block.blank{
    background:transparent; border:1px dashed var(--border); min-height:52px;
  }
  .block.blank:hover{ border-color:var(--accent); border-style:solid; }
  .clear-cell-btn{
    width:100%; margin-top:6px; padding:5px 10px; font-size:11.5px; font-family:inherit;
    border:1px solid var(--border); border-radius:6px; background:var(--surface);
    color:var(--muted); cursor:pointer;
  }
  .clear-cell-btn:hover{ border-color:var(--danger); color:var(--danger); }

  /* --- Priority: must / normal / if there is time ---------------- */
  .block.optional{ border:1px dashed var(--border); }
  .block.optional .cat-label, .block.optional .free-text{ opacity:.72; }
  .opt-mark{ color:var(--muted); font-size:11px; }
  .log-block-row.optional span{ color:var(--muted); }
  .opt-tag{
    font-size:10.5px; color:var(--muted); border:1px solid var(--border);
    border-radius:20px; padding:1px 7px; margin-left:2px;
  }
  .heat-block.optional{ opacity:.8; }

  /* --- Today's column in the schedule ---------------------------- */
  table.grid th.is-today{ color:var(--accent); font-weight:700; }
  .today-dot{
    display:inline-block; width:4px; height:4px; border-radius:50%;
    background:var(--accent); margin-left:4px; vertical-align:middle;
  }
  table.grid td.cell.today-col{ background:var(--accent-soft); }
  table.grid td.cell.today-col:first-of-type{ border-radius:8px 8px 0 0; }

  /* --- Weekday header: name over date --------------------------- */
  table.grid th{ line-height:1.3; }
  table.grid th .dow{ display:block; }
  table.grid th .dom{ display:block; font-size:10.5px; opacity:.8; font-weight:400; }
  table.grid th.is-today .dom{ opacity:1; }

  /* --- Tick straight from today's column ------------------------ */
  .cell-check{
    width:17px; height:17px; flex-shrink:0; padding:0;
    display:flex; align-items:center; justify-content:center;
    border:1.5px solid var(--border); border-radius:5px; background:var(--surface);
    color:var(--accent); font-size:10px; line-height:1; cursor:pointer;
    transition:background .12s, border-color .12s;
  }
  .cell-check:hover{ border-color:var(--accent); }
  .cell-check.done{ background:var(--accent); border-color:var(--accent); color:#fff; font-weight:700; }
  .cell-check:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }

  /* --- Planned load per day ------------------------------------- */
  /* A row's label is its handle: drag it to move the row. The grip only
     appears on hover, so the column stays quiet until you go looking. */
  table.grid td.rowlabel.block-label{ cursor:grab; position:relative; user-select:none; }
  table.grid td.rowlabel.block-label:active{ cursor:grabbing; }
  .drag-grip{
    position:absolute; left:2px; top:50%; transform:translateY(-50%);
    font-size:11px; color:var(--muted); opacity:0; transition:opacity .12s;
  }
  table.grid td.rowlabel.block-label:hover .drag-grip{ opacity:.55; }
  /* While a row is in flight, show every label's grip so the other rows
     read as places it can go. */
  table.grid.dragging-block .drag-grip{ opacity:.35; }
  table.grid.dragging-block td.rowlabel.block-label{ cursor:grabbing; }
  /* Which side of the hovered row it would land on. */
  table.grid td.block-label.drop-above{ box-shadow:inset 0 2px 0 var(--accent); }
  table.grid td.block-label.drop-below{ box-shadow:inset 0 -2px 0 var(--accent); }

  .history-more{
    padding:8px 2px 0; font-size:12px; color:var(--muted);
    border-top:1px solid var(--border); margin-top:6px;
  }

  table.grid td.rowlabel.load-label{ font-size:11px; opacity:.75; padding-top:6px; line-height:1.35; }
  .load-window{ display:block; font-size:10px; font-style:normal; opacity:.8; }
  table.grid td.load-cell{ text-align:center; padding:6px 3px 0; font-size:10.5px; line-height:1.5; }
  .load-total{ font-family:ui-monospace, monospace; font-weight:600; color:var(--muted); }
  .load-total.over{ color:var(--danger); }
  .load-opt{ color:var(--muted); opacity:.65; margin-left:4px; }

  /* ---------------------------------------------------------------
     The exported PNG.

     Laid out off-screen and handed to html2canvas. The week grid is a
     clone of the live table, so it needs no styles of its own here —
     only the sheet around it, and the two marks the export adds:
     a check on everything ticked off this week.
  --------------------------------------------------------------- */
  .export-sheet{
    position:fixed; left:-9999px; top:0; width:900px; padding:32px;
    background:var(--bg); color:var(--ink);
  }
  /* The day and the streak, centred across the whole sheet above
     everything else. */
  .export-datestrip{
    text-align:center; color:var(--muted); font-size:12.5px; margin-bottom:20px;
  }

  /* Two columns that finish level: the picture sets the height of the
     row and the quote card stretches to meet it.

     That only holds while the left column stays shorter than the
     picture. At the current picture height the tallest quote in the
     pool leaves about a line and a half of headroom; a much longer
     quote, or a much longer tagline, would overrun it and put the gap
     under the picture instead. */
  .export-head{ display:flex; align-items:stretch; justify-content:space-between; gap:28px; margin-bottom:26px; }
  .export-head-text{ flex:1; min-width:0; display:flex; flex-direction:column; }
  .export-sheet h1{ font-size:26px; margin:0 0 4px; font-weight:600; }
  .export-sheet .greeting-tagline{ font-size:13px; margin:0 0 8px; }
  .export-photo{
    height:180px; width:auto; max-width:330px; object-fit:cover;
    align-self:flex-start;
    border-radius:10px; display:block; flex-shrink:0;
  }
  /* The quote takes the rest of the column and centres its own text.
     Pushing a fixed-height quote to the floor instead left a hole in the
     middle of the column whenever the quote was a short one; letting the
     card itself grow puts that slack inside the card, where it reads as
     breathing room rather than a gap. */
  .export-sheet .quote-strip{
    margin:18px 0 0; font-size:14px; line-height:1.5;
    flex:1 1 auto; display:flex; flex-direction:column; justify-content:center;
  }
  .export-goals{ margin-bottom:24px; }
  .export-goals h2{ font-size:16px; margin:0 0 8px; font-weight:600; }
  .export-goals div{ font-size:13px; padding:3px 0; }
  .export-goals div.lvl-must{ font-weight:600; }
  .export-goals div.lvl-dream{ color:var(--muted); font-style:italic; }

  /* The completed-block check. Same shape as the live tick box, but it
     is a mark rather than a control. */
  .done-tick{
    display:inline-flex; align-items:center; justify-content:center;
    width:15px; height:15px; border-radius:4px; flex-shrink:0;
    background:var(--accent); color:#fff; font-size:10px; font-weight:700; line-height:1;
  }
  .block-foot .done-tick{ margin-left:auto; }

  .export-legend{
    display:flex; align-items:center; gap:14px; flex-wrap:wrap;
    margin-top:14px; font-size:12px; color:var(--muted);
  }
  .export-legend .lg-swatch{ display:inline-block; width:8px; height:8px; border-radius:2px; margin-right:5px; }
  .export-legend .done-tick{ width:11px; height:11px; font-size:8px; margin-right:5px; }
