/* Hone · Calendar. The page-specific rules; the tokens are the SAME values
 * as style.css, repeated here so this sheet stands alone and every var()
 * it reads is one it defines (tests/test_css_tokens.py).
 *
 * The design laws from style.css apply unchanged: ONE accent, and it only
 * ever means done, progress, today. Monospace for data only: times, counts,
 * week numbers. Motion under 220ms. Depth from light, not shadow. */
:root{
  --bg:#080a0d; --bg2:#0c1014; --panel:#11161c; --line:#1b222b; --line2:#242d38;
  --ink:#eaf0f7; --dim:#8d9aab; --faint:#7d8a9a;
  --accent:#6ee7a8; --accent-dk:#2f6b4d; --warn:#e6bd6d; --bad:#f08b8b;
  --card:#11161c; --dimline:#2c3644;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,monospace;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
  /* aliases the calendar rules read, each mapped onto the system above */
  --paper:var(--bg); --surface:var(--panel); --surface-2:var(--bg2); --surface-3:var(--line);
  --ink-2:var(--dim); --ink-3:var(--faint); --rule:var(--line); --rule-2:var(--line2);
  --accent-2:#8df0bd; --on-accent:#080a0d; --accent-soft:rgba(110,231,168,.13);
  --done:var(--accent); --done-soft:rgba(110,231,168,.13);
  --soon:var(--warn); --late:var(--bad); --late-soft:rgba(240,139,139,.12); --star:var(--warn);
  --focus:var(--accent);
  --shadow:0 1px 0 rgba(255,255,255,.03) inset;
  --r:6px;
}
/* A bare <a> is the text's own colour, never the browser's blue; the same
   base as style.css, held by tests/test_no_link_wears_the_browsers_default_blue.py. */
a{color:inherit}
/* THE HIDDEN ATTRIBUTE MUST WIN. A section that sets its own display (the
   welcome card is a flex row, the starter chips a flex column) outranks the
   browser's [hidden]{display:none}, so `el.hidden = true` did nothing to
   either: the sign-in card stayed up for a signed-in learner, and the
   starter chips stayed up over a board with 24 tasks on it. One rule, above
   every layout rule, so the attribute means what it says everywhere. */
[hidden]{display:none!important}
*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:15px;line-height:1.45;-webkit-font-smoothing:antialiased}
.wrap{max-width:1200px;margin:0 auto;padding:22px 20px 60px;display:flex;flex-direction:column;gap:14px}
/* Installed on a phone the page runs edge to edge (viewport-fit=cover, a
   translucent status bar), so its own padding has to clear the notch and
   the home indicator. In a browser tab every inset is zero and this is
   the line above. */
.wrap{padding:max(22px,env(safe-area-inset-top)) max(20px,env(safe-area-inset-right)) calc(60px + env(safe-area-inset-bottom)) max(20px,env(safe-area-inset-left))}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
input,select{font:inherit}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:2px}
/* Off the top of the page until the keyboard reaches it, then a button
   that jumps past the header to the composer. */
.skip{position:absolute;left:12px;top:-60px;z-index:300;background:var(--accent);color:var(--on-accent);padding:10px 14px;border-radius:8px;font-family:var(--sans);font-size:13px;font-weight:600;text-decoration:none}
.skip:focus{top:12px;outline:2px solid #fff;outline-offset:2px}
.mono{font-family:var(--sans);font-variant-numeric:tabular-nums}
.eyebrow{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}

/* ---------- masthead ---------- */
.mast{background:var(--surface);border:1px solid var(--rule);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.mast-top{display:flex;flex-wrap:wrap;align-items:flex-end;gap:14px 20px;padding:15px 18px 13px;border-bottom:1px solid var(--rule)}
.brand{display:flex;flex-direction:column;gap:3px;margin-right:auto}
.brand h1{margin:0;font-size:21px;font-weight:700;letter-spacing:-.02em;line-height:1.1}
/* THE WORDMARK IS A LINK HOME, as the other two doors' marks are; it was a
   heading that did nothing. It keeps the heading's ink and no underline. */
.brand h1 .wordmark{color:inherit;text-decoration:none}
.brand h1 .wordmark:hover{color:var(--ink)}
.periodline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.period{font-family:var(--sans);font-variant-numeric:tabular-nums;font-size:14px;font-weight:500}
.period .dim{color:var(--ink-3)}
.navgroup{display:flex;align-items:center;gap:2px}
.navbtn{width:29px;height:29px;display:grid;place-items:center;border:1px solid var(--rule);border-radius:3px;background:var(--surface-2);color:var(--ink-2);font-size:13px;line-height:1}
.navbtn:hover{border-color:var(--rule-2);color:var(--ink)}
.navbtn.today{width:auto;padding:0 10px;font-family:var(--sans);font-size:11px;letter-spacing:.06em;text-transform:uppercase}
.seg{display:flex;border:1px solid var(--rule);border-radius:3px;overflow:hidden;background:var(--surface-2)}
.seg button{padding:6px 11px;font-family:var(--sans);font-size:11px;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-2)}
.seg button + button{border-left:1px solid var(--rule)}
.seg button[aria-pressed="true"]{background:var(--accent);color:var(--on-accent)}
.pill{border:1px solid var(--rule);background:var(--surface-2);border-radius:3px;padding:6px 10px;font-family:var(--sans);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.pill[aria-pressed="true"]{border-color:var(--rule-2);color:var(--ink);background:var(--surface-3)}

.rail{display:flex;flex-wrap:wrap}
.stat{flex:1 1 0;min-width:100px;padding:10px 17px;display:flex;flex-direction:column;gap:1px;border-right:1px solid var(--rule)}
.stat b{font-family:var(--sans);font-variant-numeric:tabular-nums;font-size:21px;font-weight:600;letter-spacing:-.02em;line-height:1.15}
.stat.is-late b{color:var(--late)}
.stat.is-done b{color:var(--done)}
.progwrap{flex:2 1 200px;padding:12px 17px;display:flex;flex-direction:column;gap:7px;justify-content:center}
.progtop{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.progpct{font-family:var(--sans);font-size:12px;font-weight:600;color:var(--ink-2);font-variant-numeric:tabular-nums}
.bar{height:6px;background:var(--surface-3);border-radius:99px;overflow:hidden}
.bar span{display:block;height:100%;background:var(--accent);border-radius:99px;transition:width .28s ease}
.bar.full span{background:var(--done)}

/* ---------- my day ---------- */
.myday{background:var(--surface);border:1px solid var(--rule);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.mdhead{display:flex;align-items:baseline;gap:10px;padding:10px 14px;border-bottom:1px solid var(--rule);flex-wrap:wrap}
.mdhead .sun{color:var(--soon);font-size:12px}
.mdtitle{font-size:14px;font-weight:600;letter-spacing:-.01em}
.mdcount{font-family:var(--sans);font-size:11px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.mdactions{margin-left:auto;display:flex;gap:6px}
.mdlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:0 12px;padding:6px 8px}
.mdempty{padding:10px 14px;font-size:13px;color:var(--ink-3)}
/* The reviews that are due, inside My Day: the same amber rows the week
   grid draws, under one small heading, above the person's own picks. */
.mdreview{padding:8px 10px 6px;display:flex;flex-direction:column;gap:2px}
.mdreview .eyebrow{padding:0 6px 2px}
.mdreview+.mdlist{border-top:1px solid var(--rule)}
.sugg{border-top:1px solid var(--rule);background:var(--surface-2);padding:8px 10px;display:flex;flex-direction:column;gap:2px}
.suggrow{display:flex;align-items:center;gap:8px;padding:4px 5px;border-radius:3px}
.suggrow:hover{background:var(--surface-3)}
.suggrow .t{flex:1;min-width:0;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.suggwhy{font-family:var(--sans);font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.suggwhy.late{color:var(--late)}
.addmini{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;border:1px solid var(--rule-2);border-radius:3px;padding:2px 7px;color:var(--ink-2);background:var(--surface)}
.addmini:hover{border-color:var(--accent);color:var(--accent)}

/* ---------- composer ---------- */
.composer{display:flex;flex-wrap:wrap;gap:8px;align-items:center;background:var(--surface);border:1px solid var(--rule);border-radius:var(--r);padding:9px 10px 9px 12px;box-shadow:var(--shadow)}
.composer input[type="text"]{flex:1 1 260px;min-width:0;border:none;background:none;color:var(--ink);padding:5px 2px}
.composer input::placeholder{color:var(--ink-3)}
.composer input:focus{outline:none}
.composer select{font-family:var(--sans);font-size:12px;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:6px 8px}
.addbtn{padding:7px 15px;background:var(--accent);color:var(--on-accent);border-radius:3px;font-family:var(--sans);font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase}
.addbtn:hover{background:var(--accent-2)}
.hint{margin:-8px 0 -2px;font-family:var(--sans);font-size:11px;color:var(--ink-3);padding:0 2px}
/* An example never breaks in half: "Dentist thu at 2:30pm !" wrapping
   between the time and the ! left the ! sitting alone on the next line,
   reading as a token of its own rather than part of the sentence. */
.hint code{background:var(--surface-3);border-radius:2px;padding:1px 4px;color:var(--ink-2);white-space:nowrap}
/* THE ECHO READS AS OUTPUT, NOT AS BOILERPLATE: brighter than the hint it
   replaces, and led by an arrow so it is plainly the box answering rather
   than more instructions. See the comment in calendar.html. */
.hint .echo{color:var(--ink);font-family:var(--sans)}
.hint .echo::before{content:"\2192\00a0";color:var(--accent)}

/* ---------- notices ---------- */
.notice{display:flex;flex-wrap:wrap;align-items:center;gap:10px;border:1px solid var(--rule);border-radius:var(--r);padding:9px 13px;background:var(--surface-2);font-size:13px;color:var(--ink-2);margin-bottom:8px}
.notice:last-child{margin-bottom:0}
.notice.late{background:var(--late-soft);border-color:var(--late);color:var(--late)}
.linkbtn{font-family:var(--sans);font-size:11px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;border-bottom:1px solid currentColor;padding-bottom:1px}
.notice .spacer{margin-left:auto}

/* ---------- week board ---------- */
.board{border:1px solid var(--rule);border-radius:var(--r);background:var(--rule);box-shadow:var(--shadow);overflow:hidden;display:grid;gap:1px;grid-template-columns:repeat(7,minmax(0,1fr))}
.day{background:var(--surface);padding:0 0 8px;display:flex;flex-direction:column;min-height:168px}
.day.off{background:var(--surface-2)}
.day.is-today{box-shadow:inset 0 2px 0 var(--accent)}
.dayhead{display:flex;align-items:baseline;gap:6px;padding:9px 10px 7px;border-bottom:1px solid var(--rule);margin-bottom:5px}
.dow{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}
.dnum{font-family:var(--sans);font-size:14px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink-2)}
.day.is-today .dnum,.day.is-today .dow{color:var(--accent)}
.day.has-late .dnum{color:var(--late)}
.daycount{margin-left:auto;font-family:var(--sans);font-size:10px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.tasks{display:flex;flex-direction:column;gap:1px;padding:0 4px;flex:1}
/* THE ONLY WAY TO ADD ANYTHING TO A DAY, and it was 26px tall. The dashed
   border appears on hover, which no phone has, so on a phone this was a
   small grey label that happened to be the control. */
.dayadd{margin:6px 6px 0;padding:9px 4px;min-height:32px;font-family:var(--sans);font-size:11px;color:var(--ink-3);text-align:left;border:1px dashed transparent;border-radius:3px}
.day:hover .dayadd{border-color:var(--rule-2);color:var(--ink-2)}

/* ---------- task ---------- */
.task{display:flex;align-items:flex-start;gap:6px;padding:5px 6px;border-radius:3px;position:relative}
.task:hover{background:var(--surface-2)}
.check{flex:none;width:15px;height:15px;margin-top:2px;border:1.5px solid var(--rule-2);border-radius:3px;display:grid;place-items:center;background:var(--surface)}
.check:hover{border-color:var(--accent)}
.check svg{width:9px;height:9px;opacity:0;transition:opacity .12s ease}
.task.done .check{background:var(--done);border-color:var(--done)}
.task.done .check svg{opacity:1;stroke:var(--on-accent)}
.tbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ttitle{font-size:13.5px;line-height:1.35;overflow-wrap:break-word;cursor:pointer;text-align:left;align-self:flex-start;border-bottom:1px solid transparent}
.ttitle:hover{border-bottom-color:var(--rule-2)}
.task.done .ttitle{color:var(--ink-3);text-decoration:line-through;text-decoration-thickness:1px}
.tmeta{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.mchip{font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);display:inline-flex;align-items:center;gap:4px}
.mchip.time{color:var(--ink-2)}
.mchip.overdue{color:var(--late)}
.mchip.cat{color:var(--ink-2)}
/* A deadline today or tomorrow, in the warn colour; a passed one wears .overdue. */
.mchip.soon{color:var(--warn)}
.dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--accent)}
.star{flex:none;width:17px;height:17px;margin-top:1px;display:grid;place-items:center;color:var(--rule-2);font-size:11px;line-height:1;border-radius:3px}
.star:hover{color:var(--star)}
.star.on{color:var(--star)}
.task .star{opacity:0}
.task:hover .star,.task .star.on,.task:focus-within .star{opacity:1}
.tacts{display:flex;gap:1px;flex:none;opacity:0;transition:opacity .12s ease}
.task:hover .tacts,.task:focus-within .tacts{opacity:1}
.tacts button{width:19px;height:19px;display:grid;place-items:center;color:var(--ink-3);font-family:var(--sans);font-size:11px;border-radius:3px;line-height:1}
.tacts button:hover{background:var(--surface-3);color:var(--ink)}
.tacts button.del:hover{color:var(--late)}
@media (prefers-reduced-motion: reduce){*{transition:none!important;animation:none!important}}

/* ---------- day (schedule) view ---------- */
.dayview{display:grid;grid-template-columns:minmax(0,1fr) 268px;gap:14px;align-items:start}
.sched{border:1px solid var(--rule);border-radius:var(--r);background:var(--surface);box-shadow:var(--shadow);overflow:hidden}
.schedhead{display:flex;align-items:baseline;gap:9px;padding:9px 13px;border-bottom:1px solid var(--rule)}
.grid{position:relative}
.hour{display:grid;grid-template-columns:52px minmax(0,1fr);border-bottom:1px solid var(--rule);height:48px}
.hour:last-child{border-bottom:none}
.hourlab{font-family:var(--sans);font-size:10px;color:var(--ink-3);padding:3px 8px 0 0;text-align:right;font-variant-numeric:tabular-nums}
.hourslot{border-left:1px solid var(--rule);cursor:crosshair}
.hourslot:hover{background:var(--surface-2)}
.blocks{position:absolute;left:52px;right:6px;top:0;bottom:0;pointer-events:none}
.block{position:absolute;pointer-events:auto;background:var(--accent-soft);border-left:3px solid var(--accent);border-radius:3px;padding:2px 6px;overflow:hidden;text-align:left;display:flex;flex-direction:column;gap:1px}
.block:hover{filter:brightness(.97)}
.block .bt{font-family:var(--sans);font-size:9.5px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.block .bn{font-size:12px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.block.short{flex-direction:row;align-items:baseline;gap:6px;padding-top:1px}
.block.short .bn{font-size:11px}
.block.done{background:var(--surface-2);border-left-color:var(--done)}
.block.done .bn{text-decoration:line-through;color:var(--ink-3)}
.nowline{position:absolute;left:44px;right:0;height:1px;background:var(--late);z-index:3;pointer-events:none}
.nowline::before{content:"";position:absolute;left:0;top:-3px;width:7px;height:7px;border-radius:50%;background:var(--late)}
.sidecol{display:flex;flex-direction:column;gap:14px}
.panel{border:1px solid var(--rule);border-radius:var(--r);background:var(--surface);box-shadow:var(--shadow);padding:12px 13px;display:flex;flex-direction:column;gap:9px}
.panel h2{margin:0;font-size:11px}

/* ---------- month ---------- */
.monthgrid{display:grid;grid-template-columns:minmax(0,1fr) 228px;gap:14px;align-items:start}
.cal{border:1px solid var(--rule);border-radius:var(--r);background:var(--rule);box-shadow:var(--shadow);overflow:hidden;display:grid;gap:1px;grid-template-columns:repeat(7,minmax(0,1fr))}
.calhead{background:var(--surface-2);padding:6px 8px;font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}
.cell{background:var(--surface);min-height:94px;padding:6px 7px;display:flex;flex-direction:column;gap:3px;text-align:left;align-items:stretch;width:100%}
.cell.pad{background:var(--surface-2)}
.cell:hover{background:var(--surface-3)}
.cell.is-today{box-shadow:inset 0 2px 0 var(--accent)}
.cellnum{font-family:var(--sans);font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink-2)}
.cell.pad .cellnum{color:var(--ink-3);font-weight:400}
.cell.is-today .cellnum{color:var(--accent)}
.cell.has-late .cellnum{color:var(--late)}
.chip{font-size:11px;line-height:1.3;padding:1px 5px;border-radius:2px;background:var(--surface-2);border-left:2px solid var(--accent);color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chip.done{border-left-color:var(--done);color:var(--ink-3);text-decoration:line-through}
.more{font-family:var(--sans);font-size:10px;color:var(--ink-3)}
/* The month cell on a phone: see renderMonth. Pushed to the bottom of the
   cell so the date reads first and the dots sit on one line under it. */
.dots{display:none;gap:4px;align-items:center;margin-top:auto;padding-top:3px}
.dots i{width:5px;height:5px;border-radius:50%;background:var(--ink-2);flex:none}
.dots i.done{background:var(--accent-dk)}
.dots i.due{background:var(--warn)}
.wkrow{display:flex;flex-direction:column;gap:4px}
.wktop{display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.wklabel{font-family:var(--sans);font-size:11px;font-weight:600;color:var(--ink-2);border-bottom:1px solid transparent}
.wkrow.now .wklabel{color:var(--accent)}
.wklabel:hover{border-bottom-color:var(--rule-2)}
.wkcount{font-family:var(--sans);font-size:11px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.minibar{height:4px;background:var(--surface-3);border-radius:99px;overflow:hidden}
.minibar span{display:block;height:100%;background:var(--accent);border-radius:99px}
.minibar.full span{background:var(--done)}

/* ---------- planned ---------- */
/* NOW. The one thing to do next, first thing in My Day: one title large
   enough to be the point of the card, why it is the one, and the two taps
   a person makes with the thing in front of them. Late is the late colour;
   the card never shows when there is nothing to put in it. */
.now{margin:10px 12px 0;border:1px solid var(--accent-dk);border-left:3px solid var(--accent);border-radius:var(--r);padding:10px 12px;display:flex;flex-direction:column;gap:4px;background:var(--surface-2)}
.now.late{border-color:var(--late);border-left-color:var(--late)}
.nowtop{display:flex;justify-content:space-between;align-items:center;gap:8px}
.nowwhy{font-family:var(--sans);font-size:11px;letter-spacing:.04em;color:var(--ink-2)}
.nowwhy.late{color:var(--late)}
.nowtitle{text-align:left;font-family:var(--sans);font-size:17px;font-weight:600;line-height:1.3;color:var(--ink);padding:4px 0;min-height:44px;overflow-wrap:anywhere}
.nowacts{display:flex;flex-wrap:wrap;gap:8px}
.nowdone{min-height:44px;padding:9px 20px;font-size:12px}
.nowlater{min-height:44px;padding:9px 14px}
.planned{display:flex;flex-direction:column;gap:12px}
/* PROJECTS. A #tag is a project: what is open, how far along, and the one
   next step on a day. A project with open work and no step on any day is
   what "overwhelming" is made of, so it is flagged in the warn colour and
   put first. */
.projlist{display:flex;flex-direction:column;gap:8px;padding:10px 12px}
.proj{border:1px solid var(--rule);border-radius:var(--r);padding:10px 12px;display:flex;flex-direction:column;gap:7px;background:var(--surface-2)}
.proj.stuck{border-color:var(--warn)}
.projtop{display:flex;justify-content:space-between;align-items:center;gap:8px;min-width:0}
.projname{display:flex;align-items:center;gap:7px;font-family:var(--sans);font-size:14px;font-weight:600;color:var(--ink);min-width:0;overflow-wrap:anywhere}
.projnext{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px}
.projnext.stuck .eyebrow{color:var(--warn)}
.projstep{min-height:44px;text-align:left;color:var(--ink);font-family:var(--sans);font-size:13.5px;padding:0;overflow-wrap:anywhere;text-decoration:underline;text-decoration-color:var(--rule-2);text-underline-offset:3px}
.projstep:hover{text-decoration-color:var(--accent);color:var(--accent)}
.projplan{min-height:44px;padding:6px 10px}
.group{border:1px solid var(--rule);border-radius:var(--r);background:var(--surface);box-shadow:var(--shadow);overflow:hidden}
.grouphead{display:flex;align-items:baseline;gap:9px;padding:9px 13px;border-bottom:1px solid var(--rule);background:var(--surface-2)}
.grouphead.late{background:var(--late-soft)}
.grouphead.late .eyebrow{color:var(--late)}
.grouplist{display:flex;flex-direction:column;gap:1px;padding:5px 7px}
.task.row .ttitle{font-size:14px}
/* ONE LINE PER TASK IN THE WEEK GRID. Seven columns on a laptop are about
   165px each, and "Confirm work shift" and "9:30AM-10:15AM" both wrapped,
   so a three-word task became a four-line block and a full day read as a
   wall. The full title is on the row's tooltip and in the panel. Below
   460px the grid is one column a day and there is room to wrap. */
.board .day .ttitle{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;width:100%;align-self:stretch}
.board .day .tmeta{flex-wrap:nowrap;overflow:hidden}
.board .day .mchip{white-space:nowrap}
@media (max-width:460px){
  .board .day .ttitle{-webkit-line-clamp:none;display:block}
  .board .day .tmeta{flex-wrap:wrap}
}
.task.row{padding:6px 7px}
/* DONE, BY WEEK: a record that opens on a tap of its head, shut by default. */
.donewk>summary{list-style:none;cursor:pointer;min-height:44px;align-items:center}
.donewk>summary::-webkit-details-marker{display:none}
.donewk>summary .mdcount::after{content:"\00a0\00b7\00a0show"}
.donewk[open]>summary .mdcount::after{content:"\00a0\00b7\00a0hide"}
.grouphead.sub{border-top:1px solid var(--rule)}

/* THE WEEKLY REVIEW. One card in My Day on the day, one bar in Planned any
   day, and a sheet of at most three steps over exactly the tasks that need a
   decision. A row is one line of title over a row of 44px controls, so the
   whole thing works with a thumb; the warn colour marks what is waiting on
   a decision, the accent what has one. */
.wkreview{margin:10px 12px 0;border:1px solid var(--rule-2);border-left:3px solid var(--warn);border-radius:var(--r);padding:10px 12px;display:flex;flex-direction:column;gap:6px;background:var(--surface-2)}
.wkreview .nowwhy{color:var(--warn)}
.wkline{margin:0;font-size:13px;line-height:1.5;color:var(--ink-2)}
.reviewbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;border:1px dashed var(--rule-2);border-radius:var(--r);padding:10px 12px;background:var(--surface)}
.reviewbar.due{border-style:solid;border-color:var(--warn)}
.rvline{flex:1 1 240px;font-size:13px;line-height:1.5;color:var(--ink-2)}
.rvgo{min-height:44px;padding:9px 16px;font-size:12px}
.rvwhere{margin:-6px 0 0;font-family:var(--sans);font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3)}
.rvcount{margin:0;font-family:var(--sans);font-size:12px;color:var(--accent)}
.rvbody{display:flex;flex-direction:column;gap:10px}
.rvrows{display:flex;flex-direction:column;gap:8px}
.rvrow,.rvproj{border:1px solid var(--rule);border-radius:var(--r);padding:8px 10px;display:flex;flex-direction:column;gap:6px;background:var(--surface-2)}
.rvrow.settled,.rvproj.ok{border-color:var(--accent-dk)}
.rvrow.dropped{opacity:.72}
.rvtitle{font-size:14px;line-height:1.4;color:var(--ink);overflow-wrap:anywhere;display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px}
.rvsub{flex:1 1 160px;font-size:13px;color:var(--ink-2);overflow-wrap:anywhere;align-self:center}
.rvacts{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.rvacts .pill{min-height:44px;padding:8px 12px}
.rvacts .pill[aria-pressed="true"]{border-color:var(--accent);color:var(--accent)}
.rvdrop{color:var(--late)}
.rvsel{font-family:var(--sans);font-size:13px;color:var(--ink);background:var(--surface);border:1px solid var(--rule-2);border-radius:3px;padding:8px 10px;min-height:44px;max-width:100%}
.pill.rvnav{min-height:44px;padding:9px 16px;font-size:12px}
.rvsum{margin:0;font-size:14px;line-height:1.6;color:var(--ink)}

/* ---------- anytime ---------- */
.anytime{border:1px solid var(--rule);border-radius:var(--r);background:var(--surface);box-shadow:var(--shadow);padding:10px 12px;display:flex;flex-direction:column;gap:7px}
.anyhead{display:flex;align-items:baseline;gap:9px}
.anylist{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:1px 10px}
.empty{font-size:12.5px;color:var(--ink-3);padding:2px}

/* ---------- detail pane ---------- */
.backdrop{position:fixed;inset:0;background:rgba(12,15,20,.22);z-index:25}
.pane{position:fixed;top:0;right:0;bottom:0;width:min(372px,100%);background:var(--surface);border-left:1px solid var(--rule);box-shadow:-16px 0 44px -34px rgba(0,0,0,.7);z-index:30;display:flex;flex-direction:column;gap:0;overflow-y:auto}
.modalback{position:fixed;inset:0;background:rgba(12,15,20,.34);z-index:40;display:grid;place-items:center;padding:20px}
.modal{width:min(400px,100%);background:var(--surface);border:1px solid var(--rule);border-radius:6px;box-shadow:0 24px 60px -30px rgba(0,0,0,.6);padding:20px 22px 22px;display:flex;flex-direction:column;gap:14px;max-height:88vh;overflow-y:auto}
.modal h2{margin:0;font-size:18px;font-weight:600;letter-spacing:-.015em}
.modal p{margin:0;font-size:13.5px;color:var(--ink-2);line-height:1.5}
.modal input[type="email"]{width:100%;background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:9px 10px;color:var(--ink);font-size:14px}
.modalrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.modalrow .spacer{margin-left:auto}
.mbtn{border:1px solid var(--rule);border-radius:3px;padding:7px 13px;font-family:var(--sans);font-size:11px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-2);background:var(--surface-2)}
.mbtn:hover{border-color:var(--rule-2);color:var(--ink)}
.mbtn.primary{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.mbtn.primary:hover{background:var(--accent-2)}
.mbtn.danger{color:var(--late)}
.mbtn.danger:hover{border-color:var(--late);background:var(--late-soft)}
.modal .who{font-family:var(--sans);font-size:12px;color:var(--ink);background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:8px 10px;overflow-wrap:anywhere}
.modal .divider{height:1px;background:var(--rule);margin:2px 0}
/* MANY AT ONCE. The sheet a brain dump lands in: one line per task, the
   composer's own grammar on every line. */
.modal textarea.many{width:100%;min-height:170px;background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:9px 10px;color:var(--ink);font:inherit;font-size:14px;line-height:1.45;resize:vertical}
.composer .many{min-height:44px}
.modal .addbtn{min-height:44px;padding:9px 18px;font-size:12px}
/* Notifications on this device: two settings and one button. The rows are
   labels, so the whole row is the tap target and clears 44px. */
.notify{display:flex;flex-direction:column;gap:8px}
.notify-rows{display:flex;flex-direction:column;gap:2px}
.notify-row{display:flex;align-items:center;gap:10px;min-height:44px;font-size:13.5px;color:var(--ink);cursor:pointer}
.notify-row input[type="checkbox"]{width:18px;height:18px;margin:0;accent-color:var(--accent)}
.notify select{font-family:var(--sans);font-size:13px;color:var(--ink);background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:7px 8px;min-height:36px}
.pill.acct{max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:none;letter-spacing:.02em}
.notice.good{background:var(--done-soft);border-color:var(--done);color:var(--done)}
.panehead{display:flex;align-items:center;gap:9px;padding:12px 14px;border-bottom:1px solid var(--rule);position:sticky;top:0;background:var(--surface);z-index:2}
.panehead .spacer{margin-left:auto}
.panebody{padding:12px 14px 22px;display:flex;flex-direction:column;gap:14px}
.ptitle{width:100%;background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:8px 9px;color:var(--ink);font-size:15px;line-height:1.35}
.field{display:flex;flex-direction:column;gap:5px}
.field > label{font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}
.field input[type="date"],.field input[type="time"],.field input[type="text"],.field select{
  background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:6px 8px;color:var(--ink);font-size:13px;width:100%;
}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.quickchips{display:flex;flex-wrap:wrap;gap:5px}
.qchip{border:1px solid var(--rule);border-radius:3px;padding:3px 8px;font-family:var(--sans);font-size:10.5px;color:var(--ink-2);background:var(--surface-2)}
.qchip:hover{border-color:var(--accent);color:var(--accent)}
.toggles{display:flex;flex-wrap:wrap;gap:6px}
.tgl{display:flex;align-items:center;gap:6px;border:1px solid var(--rule);border-radius:3px;padding:5px 9px;font-size:12px;color:var(--ink-2);background:var(--surface-2)}
.tgl[aria-pressed="true"]{border-color:var(--accent);color:var(--accent);background:var(--accent-soft)}
.steps{display:flex;flex-direction:column;gap:3px}
.step{display:flex;align-items:center;gap:7px;padding:3px 2px}
.step input[type="text"]{flex:1;background:none;border:none;border-bottom:1px solid transparent;color:var(--ink);font-size:13px;padding:2px 0}
.step input[type="text"]:focus{outline:none;border-bottom-color:var(--rule-2)}
.step.done input[type="text"]{color:var(--ink-3);text-decoration:line-through}
.stepdel{color:var(--ink-3);font-family:var(--sans);font-size:11px;width:18px;height:18px;border-radius:3px}
.stepdel:hover{color:var(--late);background:var(--surface-3)}
.danger{align-self:flex-start;font-family:var(--sans);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--late);border:1px solid var(--rule);border-radius:3px;padding:6px 11px}
.danger:hover{border-color:var(--late);background:var(--late-soft)}
.panemeta{font-family:var(--sans);font-size:10px;color:var(--ink-3);border-top:1px solid var(--rule);padding-top:10px}

/* ---------- footer ---------- */
.foot{display:flex;flex-wrap:wrap;gap:8px 20px;align-items:center;justify-content:space-between;padding-top:4px;font-family:var(--sans);font-size:10.5px;color:var(--ink-3)}
.keys{display:flex;flex-wrap:wrap;gap:11px}
kbd{font-family:var(--sans);font-size:10px;background:var(--surface);border:1px solid var(--rule);border-bottom-width:2px;border-radius:3px;padding:1px 4px;color:var(--ink-2)}

@media (max-width:980px){
  .monthgrid,.dayview{grid-template-columns:minmax(0,1fr)}
  .board{grid-template-columns:repeat(4,minmax(0,1fr))}
}
@media (max-width:760px){
  .pane{top:auto;left:0;width:100%;max-height:86vh;border-left:none;border-top:1px solid var(--rule);border-radius:8px 8px 0 0}
}
@media (max-width:720px){
  .board{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cell{min-height:72px}
  .chip{display:none}
  .more{display:none}
  .dots{display:flex}
  .stat{min-width:86px;padding:9px 12px}
  .stat b{font-size:19px}
  /* TWO LINES RESERVED FOR EVERY LABEL, so the numbers sit on one line.
     "Due for review" wraps at this width and "Open" does not, which
     pushed one number a line below the other two and left the row
     looking dropped. */
  .stat .eyebrow{min-height:2.2em}
  /* A phone shows the three tiles a person acts on; Overdue comes back
     the moment it is not zero (calendar.js marks it "less" only at zero). */
  .stat.less{display:none}
  /* No keyboard, no keyboard hints. */
  .keys{display:none}
  /* THE TOP OF A PHONE IS THREE ROWS: the period, the views, then done,
     search and the account on one line. It was six rows of controls
     before anything a person could act on. */
  .mast-top{padding:12px 14px 10px;gap:8px 10px}
  .brand h1{font-size:19px}
  .periodline{width:100%}
  .seg{width:100%}
  .seg button{flex:1;text-align:center;padding:8px 4px}
  .search{flex:1 1 70px;min-width:70px;min-height:36px;padding:6px 8px}
  /* ONE BOX, THEN ONE ROW. At 390px the box, the day and both buttons
     wrapped into a row of two and a row of two with a hole beside them.
     The box takes the whole width; the day and the buttons share the
     line under it. */
  .composer{padding:10px 12px;gap:8px}
  .composer input[type="text"]{flex:1 1 100%;min-height:40px;padding:6px 2px}
  .composer select{flex:1 1 auto;min-height:44px}
  .composer .addbtn,.composer .many{min-height:44px;flex:0 0 auto}
  .pill{padding:8px 9px;min-height:36px}
  .pill.acct{max-width:120px}
  /* THE SYNTAX LINE STAYS PUT. It used to be display:none here and shown
     on .composer:focus-within, but the day picker is inside the composer,
     so tapping it kept focus, drew this line underneath the system's own
     dropdown where it could not be read, and then took it away again the
     moment the dropdown closed. The line was unreadable on a phone by
     construction. Four lines of 11px is the honest price of a box that
     expects a grammar. */
  .hint{margin:2px 0 0;line-height:1.5}
  .welcome-btn{flex:1 1 100%}
  .rail.is-empty{display:none}
  .install-btns{flex:1 1 100%}
  .install-btn{flex:1 1 auto}
}
@media (max-width:460px){
  .board{grid-template-columns:minmax(0,1fr)}
  .day{min-height:0}
}

/* THE SIGN-IN CARD, first thing on the page for a visitor with no
   session. One accent-edged surface, one sentence about what signing in
   is for, one button in the composer's own style. Hidden the moment there
   is a session; the pill in the header stays for later. */
.welcome{display:flex;flex-wrap:wrap;align-items:center;gap:12px 22px;background:var(--surface);
  border:1px solid var(--accent-dk);border-left:3px solid var(--accent);border-radius:var(--r);
  box-shadow:var(--shadow);padding:14px 16px}
.welcome-copy{flex:1 1 320px;min-width:0}
.welcome-copy h2{margin:0 0 4px;font-family:var(--sans);font-size:16px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
.welcome-copy p{margin:0;font-size:13px;line-height:1.5;color:var(--ink-2)}
.welcome-btn{min-height:44px;padding:9px 20px;font-size:12px;flex:0 0 auto}
/* THE TWO LINKS IN THAT SENTENCE WERE THE BROWSER'S OWN BLUE. Nothing on
   this page styles a bare <a>, and "honecoding" and "honejobs" in the sign-in
   card were the only two bare ones: rgb(0,0,238) on the card, 1.93:1, on the
   first thing a visitor without a session sees. The footer's pair carry an
   inline color:inherit; these get the tag link's idiom, ink with a rule under
   it, accent on hover. tests/test_no_link_wears_the_browsers_default_blue.py
   measures every anchor on every public page against the browser's default
   so the next bare one fails at home. */
.welcome-copy p a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--rule-2)}
.welcome-copy p a:hover{color:var(--accent);border-bottom-color:var(--accent)}
/* In use without an account: one line and the button. */
.welcome.slim{padding:9px 14px;gap:8px 16px}
.welcome.slim .welcome-copy p{display:none}
.welcome.slim .welcome-copy h2{margin:0;font-size:14px}
.welcome.slim .welcome-btn{min-height:40px;padding:7px 16px}
/* THE EMPTY BOARD. No example tasks: a week full of somebody else's dentist
   reads as clutter, not as help. Three chips that fill the composer teach
   the syntax by being typed. They are buttons, so they meet the 44px law. */
.starter{border:1px dashed var(--rule-2);border-radius:var(--r);padding:12px 14px;display:flex;flex-direction:column;gap:9px}
.starter p{margin:0;font-size:13.5px;color:var(--ink-2);line-height:1.5}
.starter p b{color:var(--ink)}
.steps3{margin:0;padding:0 0 0 20px;font-size:13.5px;color:var(--ink-2);line-height:1.6}
.steps3 li{padding-left:2px}
.starter-chips{display:flex;flex-wrap:wrap;gap:8px}
.starter-chip{min-height:44px;padding:8px 13px;border:1px solid var(--rule-2);border-radius:999px;background:var(--surface-2);
  color:var(--ink);font-family:var(--mono);font-size:13px;text-align:left}
.starter-chip:hover{border-color:var(--accent);color:var(--accent)}

/* THE HOME SCREEN. One line, shown once there is something on the board
   and never inside the installed app: on Chrome and Android the button is
   the browser's own install prompt; on an iPhone, where no page may ask,
   the sentence says where Safari keeps it. "Not now" is remembered. */
.install{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;background:var(--surface);
  border:1px solid var(--rule);border-radius:var(--r);padding:12px 16px}
.install-copy{flex:1 1 300px;min-width:0}
.install-copy h2{margin:0 0 3px;font-family:var(--sans);font-size:14px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
.install-copy p{margin:0;font-size:12.5px;line-height:1.5;color:var(--ink-2)}
.install-btns{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.install-btn{min-height:44px;padding:9px 18px;font-size:12px}
.install-later{min-height:44px}

/* SIXTEEN PIXELS OR iOS ZOOMS THE PAGE. Focus a field under 16px on an
   iPhone and Safari zooms in; the zoomed page is wider than the screen, so
   the masthead runs off the top and the phone starts scrolling sideways.
   style.css has carried this floor since the report that found it. This
   page is the one page in public/ that does not load style.css, so every
   field on it, the box, the search, the day picker, the note, the email,
   the date and time, zoomed. Same rule, same reason, on this sheet too;
   tests/test_portrait.py now follows every page to its own stylesheets so
   a third sheet cannot escape it the way this one did. */
@media(pointer:coarse){
  input:not([type=range]):not([type=checkbox]):not([type=radio]),
  textarea, select, [contenteditable="true"]{
    font-size:16px!important;
  }
}

/* AN EMPTY BOX STILL TAKES ITS GAP. The notices strip is a permanent
   child of a flex column with a 14px gap, so with nothing in it the page
   carried 28px of dead black between the composer and My Day where a
   card looked like it had failed to load. */
#notices:empty{display:none}

/* ---------- search ---------- */
.search{font-family:var(--sans);font-size:12px;color:var(--ink);background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:6px 9px;min-height:29px;width:150px}
.search::placeholder{color:var(--ink-3)}
.search:focus{border-color:var(--accent-dk);outline:none}

/* ---------- the hint and the shortcuts sheet ---------- */
/* The separator belongs TO the button, so the two wrap to a new line
   together instead of leaving a dot stranded at the end of the one above. */
.hint .linkbtn::before{content:"\00b7\00a0";color:var(--ink-3);text-decoration:none;display:inline-block}
.hint .linkbtn{border-bottom:none;text-decoration:underline;text-underline-offset:2px;color:var(--ink-2);font-size:11px;letter-spacing:.06em;min-height:44px;padding:0 2px}
.syn{display:flex;flex-direction:column;gap:6px}
.synrow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);gap:10px;align-items:baseline;font-size:12.5px;color:var(--ink-2)}
.synrow code{font-family:var(--mono);font-size:12px;color:var(--ink);background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:2px 6px;overflow-wrap:anywhere}

/* ---------- notes and links ---------- */
.notearea{width:100%;background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:8px 9px;color:var(--ink);font:inherit;font-size:13.5px;line-height:1.45;resize:vertical;min-height:70px}
.notearea:focus{border-color:var(--accent-dk);outline:none}
.linkrow{display:flex;gap:6px;align-items:center}
.linkrow input[type="url"]{flex:1;min-width:0;background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:6px 8px;color:var(--ink);font-size:13px}
.linkrow .qchip{min-height:32px;display:inline-flex;align-items:center;text-decoration:none;white-space:nowrap}
.fieldnote{font-family:var(--sans);font-size:11px;color:var(--late);min-height:0}
.fieldnote:empty{display:none}
a.mchip.tlink{color:var(--ink-2);text-decoration:none;border-bottom:1px solid var(--rule-2)}
a.mchip.tlink:hover{color:var(--accent);border-bottom-color:var(--accent)}
.nowjoin{min-height:44px;padding:9px 14px;display:inline-flex;align-items:center;text-decoration:none;color:var(--ink);border-color:var(--accent-dk)}
.nowjoin:hover{border-color:var(--accent);color:var(--accent)}
.daynote{text-align:left;width:100%;border:1px solid var(--rule);border-radius:3px;background:var(--surface-2);padding:9px 10px;min-height:44px}
.daynote:hover{border-color:var(--rule-2)}
.daynote .dn{display:block;font-size:13px;line-height:1.45;color:var(--ink-2);white-space:pre-wrap;overflow-wrap:anywhere;max-height:9em;overflow:hidden}
.daynoteadd{min-height:44px;align-self:flex-start;padding:6px 10px}

/* ---------- drag between days ---------- */
.task[draggable="true"]{cursor:grab}
.task.dragging{opacity:.45}
/* PRESS AND HOLD. The row darkens while the hold is armed, and no callout
   or text selection comes up under a finger that is holding still. */
.task{-webkit-touch-callout:none}
.task.holding{background:var(--surface-3)}
@media(pointer:coarse){.task{user-select:none;-webkit-user-select:none}}
.movegrid{display:flex;flex-wrap:wrap;gap:8px}
.pill.movepill{min-height:44px;padding:9px 14px;font-size:12px;text-transform:none;letter-spacing:.02em}
.pill.movepill.is-here{border-color:var(--accent);color:var(--accent)}
.mbtn.movebtn{min-height:44px;padding:9px 16px}
.day.dragover{box-shadow:inset 0 0 0 2px var(--accent)}
.anytime.dragover{border-color:var(--accent)}

/* ---------- the feed ---------- */
.feed{display:flex;flex-direction:column;gap:8px}
.feed p{font-size:12.5px}
.feedurl{width:100%;font-family:var(--mono);font-size:11.5px;color:var(--ink);background:var(--surface-2);border:1px solid var(--rule);border-radius:3px;padding:8px 9px;overflow-wrap:anywhere}
.notice .act{margin-right:10px}

/* MORE THAN TWO TOPICS ON A DAY: one row. */
.due.duegroup .dl{font-weight:600}

/* DATA, and only data, in monospace. */
.period,.stat b,.dnum,.daycount,.progpct,.wkcount,.hourlab,.block .bt,.mchip.time,
.cellnum,.mdcount,.who,kbd,.hint code,code{font-family:var(--mono)}
.eyebrow,.dow,.calhead,.seg button,.pill,.addbtn,.navbtn.today,.linkbtn,.addmini,.mbtn,
.field > label,.verdict,.tag,.mchip,.suggwhy,.overdue,.qchip,.dayadd,.hint,.foot{letter-spacing:.06em}
/* Hone's category is a word, not a colour: the one accent stays for progress. */
.dot{display:none}
.mchip.cat{color:var(--dim)}
/* Topics coming back from schedule.py: read-only, warn-coloured, never a checkbox. */
.due{display:flex;align-items:flex-start;gap:6px;padding:4px 6px;border-radius:3px;
  border-left:2px solid var(--warn);background:rgba(230,189,109,.08);text-decoration:none;color:inherit}
.due:hover{background:rgba(230,189,109,.14)}
.due .dl{font-size:12.5px;line-height:1.35;color:var(--ink)}
.due .dm{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--warn)}
.due .dm b{font-family:var(--mono);font-weight:600}
.chip.due-chip{border-left-color:var(--warn);color:var(--warn)}
/* A deadline on the month: the warn colour, like a review coming back. */
.chip.deadline{border-left-color:var(--warn);color:var(--warn)}
.dots i.deadline{background:var(--warn)}
.gsiWrap{display:flex;justify-content:center;min-height:44px}
