/* ============================================================
   GYST — design tokens
   The four family members are the only saturated colour in the
   system. Everything else is a green-cast neutral, so a list
   with four contributors never reads as confetti.
   ============================================================ */
:root{
  color-scheme: light dark;

  --bg:#F4F6F2;
  --surface:#FFFFFF;
  --surface-2:#EBEEE7;
  --border:#DCE1D7;
  --border-strong:#BFC7B8;
  --ink:#1A201B;
  --ink-2:#525A50;
  --ink-3:#7D867B;

  --p-shawn:#2F6DB5;
  --p-jenn:#CE5138;
  --p-flynn:#2E8A5B;
  --p-tavi:#B37F09;

  --accent:var(--p-shawn);

  --font-display:"Familjen Grotesk","Helvetica Neue",Arial,sans-serif;
  --font-body:"IBM Plex Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --font-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* Text size, set per device in Settings. Every size in the app is a
     multiple of this, so one number moves the whole thing — nothing
     should ever be a bare px font-size. */
  --fs:1;

  --t-3xs:calc(9px  * var(--fs));
  --t-2xs:calc(10px * var(--fs));
  --t-xs:calc(11px  * var(--fs));
  --t-sm:calc(13px  * var(--fs));
  --t-base:calc(15px * var(--fs));
  --t-md:calc(17px  * var(--fs));
  --t-lg:calc(21px  * var(--fs));
  --t-xl:calc(27px  * var(--fs));
  --t-2xl:calc(36px * var(--fs));

  /* The tracker bubble grows with the text, or its date would outgrow it. */
  --bub:calc(32px * var(--fs));

  --r:9px; --r-sm:5px; --r-pill:999px;
  --tabbar-h:calc(38px + 22px * var(--fs));
  --sidebar-w:236px;

  --shadow-sm:0 1px 2px rgba(26,32,27,.07);
  --shadow-lg:0 2px 6px rgba(26,32,27,.08), 0 20px 44px -20px rgba(26,32,27,.30);
}

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#141712;
    --surface:#1C1F1A;
    --surface-2:#252921;
    --border:#31362D;
    --border-strong:#4A5143;
    --ink:#E9ECE4;
    --ink-2:#A9B1A3;
    --ink-3:#7E877A;
    --p-shawn:#6FA8E0;
    --p-jenn:#F08065;
    --p-flynn:#57BE86;
    --p-tavi:#DCAE3C;
    --shadow-sm:0 1px 2px rgba(0,0,0,.4);
    --shadow-lg:0 2px 6px rgba(0,0,0,.4), 0 20px 44px -20px rgba(0,0,0,.7);
  }
}

:root[data-theme="dark"]{
  --bg:#141712;
  --surface:#1C1F1A;
  --surface-2:#252921;
  --border:#31362D;
  --border-strong:#4A5143;
  --ink:#E9ECE4;
  --ink-2:#A9B1A3;
  --ink-3:#7E877A;
  --p-shawn:#6FA8E0;
  --p-jenn:#F08065;
  --p-flynn:#57BE86;
  --p-tavi:#DCAE3C;
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  --shadow-lg:0 2px 6px rgba(0,0,0,.4), 0 20px 44px -20px rgba(0,0,0,.7);
}

/* ============================================================
   base
   ============================================================ */
*,*::before,*::after{box-sizing:border-box;}
[hidden]{display:none !important;}

html,body{height:100%;}
#root{height:100%;}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:var(--t-base);
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  overflow:hidden;
}
h1,h2,h3,h4{font-family:var(--font-display);margin:0;text-wrap:balance;letter-spacing:-.015em;}
button,input,select{font:inherit;color:inherit;}
button{background:none;border:0;cursor:pointer;padding:0;text-align:left;}
input{background:none;border:0;}
input:focus{outline:none;}

:where(button,input,a,[tabindex]):focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
  border-radius:var(--r-sm);
}

.mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;}
.eyebrow{
  font-size:var(--t-xs);
  font-weight:600;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--ink-3);
}

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

/* ============================================================
   sign-in stand-in
   ============================================================ */
.signin{
  height:100%;
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;
  gap:26px;
  padding:32px 24px calc(32px + env(safe-area-inset-bottom));
  text-align:center;
}
.signin-dots{display:flex;gap:7px;justify-content:center;}
.signin-dots i{width:11px;height:11px;border-radius:var(--r-pill);display:block;}
.signin-mark{
  font-family:var(--font-display);
  font-size:var(--t-2xl);font-weight:700;
  letter-spacing:-.035em;line-height:1;
}
.signin p{max-width:33ch;color:var(--ink-2);margin:0;}
.gbtn{
  display:inline-flex;align-items:center;gap:11px;
  text-decoration:none;color:inherit;
  background:var(--surface);
  border:1px solid var(--border-strong);
  border-radius:var(--r);
  padding:12px 20px;
  font-weight:500;
  box-shadow:var(--shadow-sm);
  transition:border-color .15s,transform .1s;
}
.gbtn:hover{border-color:var(--ink-3);}
.gbtn:active{transform:translateY(1px);}
.signin-note{
  font-size:var(--t-xs);color:var(--ink-3);max-width:40ch;
  border-top:1px solid var(--border);padding-top:15px;line-height:1.6;
}

/* ============================================================
   shell
   ============================================================ */
.shell{height:100%;display:flex;}
.sidebar{display:none;}
.main{flex:1;min-width:0;display:flex;flex-direction:column;height:100%;position:relative;}

.topbar{
  flex:none;
  display:flex;align-items:center;gap:10px;
  padding:calc(9px + env(safe-area-inset-top)) 14px 9px;
  background:var(--surface);
  border-bottom:1px solid var(--border);
  z-index:20;
}
.wordmark{
  font-family:var(--font-display);font-size:var(--t-lg);font-weight:700;
  letter-spacing:-.035em;line-height:1;
  display:flex;align-items:center;gap:9px;
}
/* The mark scales with the text-size control like everything else, so
   turning the type up does not leave a stamp-sized logo behind. The
   width/height attributes on the img are the source's, not the display
   size — they are there to reserve the right box before it loads. */
.brand{
  width:calc(26px * var(--fs));height:calc(26px * var(--fs));
  flex:none;display:block;border-radius:calc(6px * var(--fs));
}
/* On a wide screen the sidebar already shows the mark next to the
   wordmark, so the one in the topbar would just be the same logo twice
   in one view. */
@media (min-width:900px){ .topbar > .brand{display:none;} }
.topbar-spacer{flex:1;}

.netpill{
  display:inline-flex;align-items:center;gap:6px;
  border:1px solid var(--border);
  border-radius:var(--r-pill);
  padding:4px 11px 4px 9px;
  font-size:var(--t-xs);font-weight:600;letter-spacing:.03em;
  color:var(--ink-2);background:var(--surface-2);
}
.netpill i{width:7px;height:7px;border-radius:var(--r-pill);background:var(--p-flynn);display:block;}
.netpill[data-state="offline"] i{background:var(--ink-3);animation:blip 1.6s ease-in-out infinite;}
@keyframes blip{0%,100%{opacity:1}50%{opacity:.25}}

.avatar{
  width:34px;height:34px;flex:none;
  border-radius:var(--r-pill);
  display:grid;place-items:center;
  font-family:var(--font-display);font-size:var(--t-sm);font-weight:700;
  color:#fff;background:var(--accent);
  border:2px solid var(--surface);
  box-shadow:0 0 0 1.5px var(--accent);
}

.offbanner{
  flex:none;
  background:var(--ink);color:var(--bg);
  font-size:var(--t-sm);
  padding:9px 16px;
  display:flex;align-items:center;gap:9px;
}
.offbanner b{font-weight:600;}
.offbanner span{opacity:.75;}

.content{
  flex:1;min-height:0;
  overflow-y:auto;overscroll-behavior:contain;
  padding-bottom:calc(var(--tabbar-h) + 96px + env(safe-area-inset-bottom));
}
.content.no-compose{padding-bottom:calc(var(--tabbar-h) + 26px + env(safe-area-inset-bottom));}
.screen{padding:16px 14px 0;}
.wrap{max-width:1200px;margin:0 auto;}

.screen-head{display:flex;align-items:flex-end;gap:12px;margin-bottom:14px;}
.screen-head h1{font-size:var(--t-xl);font-weight:700;line-height:1.1;}
.screen-head .count{
  font-family:var(--font-mono);font-size:var(--t-sm);
  color:var(--ink-3);padding-bottom:3px;
}

/* ============================================================
   tab bar — five slots so the roadmap stays visible
   ============================================================ */
.tabbar{
  position:absolute;left:0;right:0;bottom:0;
  height:calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  padding-bottom:env(safe-area-inset-bottom);
  display:flex;
  background:var(--surface);
  border-top:1px solid var(--border);
  z-index:30;
}
.tab{
  flex:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  font-size:var(--t-2xs);font-weight:600;letter-spacing:.02em;
  color:var(--ink-3);position:relative;transition:color .15s;
}
.tab svg{width:21px;height:21px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;}
.tab[aria-current="page"]{color:var(--accent);}
.tab[data-soon="1"]{opacity:.4;}

/* ============================================================
   segmented control
   ============================================================ */
.seg{
  display:inline-flex;
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r);
  padding:3px;gap:2px;
}
.seg button{
  padding:6px 14px;
  border-radius:var(--r-sm);
  font-size:var(--t-sm);font-weight:500;
  color:var(--ink-2);
  transition:background .15s,color .15s;
  white-space:nowrap;
}
.seg button[aria-pressed="true"]{
  background:var(--surface);
  color:var(--ink);
  font-weight:600;
  box-shadow:var(--shadow-sm);
}

/* ============================================================
   panels
   ============================================================ */
.panel{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r);
  overflow:hidden;
}
.panel + .panel{margin-top:14px;}
.panel-head{
  display:flex;align-items:center;gap:10px;
  padding:13px 15px;
  border-bottom:1px solid var(--border);
}
.panel-head h2{font-size:var(--t-md);font-weight:600;}
.panel-head .grow{flex:1;}

/* ============================================================
   grocery list rows
   ============================================================ */
.list{list-style:none;margin:0;padding:0;}
.row{
  display:flex;align-items:center;gap:12px;
  padding:11px 15px;
  border-bottom:1px solid var(--border);
  position:relative;
}
.row:last-child{border-bottom:0;}
.row-main{flex:1;min-width:0;}
.row-name{
  font-size:var(--t-base);font-weight:500;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.row-meta{
  font-size:var(--t-xs);color:var(--ink-3);
  display:flex;align-items:center;gap:6px;margin-top:1px;
}
.row-meta .who{font-weight:600;color:var(--person);}
.row-qty{
  font-family:var(--font-mono);font-size:var(--t-sm);
  color:var(--ink-2);
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r-sm);
  padding:2px 7px;flex:none;
}
.row-open{
  width:26px;height:26px;flex:none;
  display:grid;place-items:center;
  color:var(--ink-3);border-radius:var(--r-sm);
}
.row-open:hover{background:var(--surface-2);color:var(--ink);}
.row-open svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}

/* the person's colour rides the checkbox — the thing you actually tap */
.check{
  width:24px;height:24px;flex:none;
  border-radius:var(--r-pill);
  border:2px solid var(--person);
  display:grid;place-items:center;
  transition:background .16s,border-color .16s;
}
.check svg{width:13px;height:13px;stroke:#fff;fill:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;opacity:0;transition:opacity .16s;}
.check[aria-pressed="true"]{background:var(--person);}
.check[aria-pressed="true"] svg{opacity:1;}
.check:hover{background:color-mix(in oklab, var(--person) 16%, transparent);}
.check[aria-pressed="true"]:hover{background:var(--person);}

/* A to-do is a sentence — "sign Flynn's permission slip before Friday" —
   where a grocery item is a word or two. On one line, at a larger text
   size, that truncates after about four words and the only way to read
   the rest is to open the menu. So these wrap to two lines and clamp
   after that; the row gets taller, which is a fair price for being able
   to read it. Grocery rows keep the single line they suit.
   Aligned to the top rather than centred, so the checkbox stays beside
   the first line instead of drifting to the middle of a tall row. */
.row[data-todo]{align-items:flex-start;}
.row[data-todo] .check,
.row[data-todo] .row-open{margin-top:1px;}
.row[data-todo] .row-name{
  white-space:normal;
  display:-webkit-box;
  -webkit-box-orient:vertical;
  -webkit-line-clamp:2;
  line-clamp:2;
  overflow:hidden;
  line-height:1.35;
}

.row.done .row-name{text-decoration:line-through;color:var(--ink-3);font-weight:400;}
.row.done .row-qty{opacity:.55;}

.pending{
  font-family:var(--font-mono);font-size:var(--t-2xs);font-weight:500;
  letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink-3);
  border:1px dashed var(--border-strong);
  border-radius:var(--r-sm);
  padding:1px 5px;
}

.empty{padding:30px 20px;text-align:center;color:var(--ink-3);font-size:var(--t-sm);}
.empty b{display:block;color:var(--ink-2);font-weight:600;margin-bottom:3px;font-size:var(--t-base);}

/* in-cart section */
.cart-toggle{
  width:100%;
  display:flex;align-items:center;gap:9px;
  padding:12px 15px;
  font-size:var(--t-sm);font-weight:600;color:var(--ink-2);
}
.cart-toggle svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .18s;}
.cart-toggle[aria-expanded="true"] svg{transform:rotate(90deg);}
.cart-toggle .grow{flex:1;}
.cart-note{
  padding:0 15px 13px;
  font-size:var(--t-xs);color:var(--ink-3);line-height:1.55;
}

/* ============================================================
   composer — fixed above the tab bar, reachable one-handed
   ============================================================ */
.composer{
  position:absolute;
  left:0;right:0;
  bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  z-index:25;
  background:var(--surface);
  border-top:1px solid var(--border);
  padding:10px 12px calc(10px);
  display:flex;
}
.composer-inner{display:flex;gap:8px;align-items:center;width:100%;}
.composer-field{
  flex:1;min-width:0;
  display:flex;align-items:center;gap:8px;
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r);
  padding:0 10px;
}
.composer-field:focus-within{border-color:var(--accent);}
.composer-field input{
  flex:1;min-width:0;
  padding:11px 0;font-size:var(--t-base);
}
.composer-field input::placeholder{color:var(--ink-3);}
.composer-qty{
  width:66px;flex:none;
  text-align:right;
  font-family:var(--font-mono);font-size:var(--t-sm);
  color:var(--ink-2);
  border-left:1px solid var(--border);
  padding-left:9px !important;
}
.btn-add{
  flex:none;
  width:44px;height:44px;
  border-radius:var(--r);
  background:var(--accent);
  display:grid;place-items:center;
  transition:opacity .15s,transform .1s;
}
.btn-add svg{width:20px;height:20px;stroke:#fff;fill:none;stroke-width:2.2;stroke-linecap:round;}
.btn-add:active{transform:scale(.95);}
.btn-add:disabled{opacity:.35;cursor:default;}

/* ============================================================
   suggestion chips + due rows
   ============================================================ */
.due-row{
  display:flex;align-items:center;gap:12px;
  padding:11px 15px;
  border-bottom:1px solid var(--border);
  width:100%;
}
.due-row:last-child{border-bottom:0;}
.due-row:hover{background:var(--surface-2);}
.due-main{flex:1;min-width:0;}
.due-name{font-weight:500;font-size:var(--t-base);}
.due-why{font-size:var(--t-xs);color:var(--ink-3);margin-top:1px;}
.due-why b{font-weight:600;color:var(--ink-2);}
.overdue-bar{
  width:52px;height:4px;flex:none;
  background:var(--surface-2);
  border-radius:var(--r-pill);
  overflow:hidden;
}
.overdue-bar i{display:block;height:100%;background:var(--ink-3);border-radius:var(--r-pill);}
.overdue-bar[data-over="1"] i{background:var(--p-jenn);}
.due-add{
  flex:none;width:28px;height:28px;
  border-radius:var(--r-pill);
  border:1px solid var(--border-strong);
  display:grid;place-items:center;color:var(--ink-2);
}
.due-add svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;}
.due-row:hover .due-add{border-color:var(--accent);color:var(--accent);}

.chips{display:flex;flex-wrap:wrap;gap:7px;padding:14px 15px;}
.chip{
  display:inline-flex;align-items:center;gap:7px;
  border:1px solid var(--border-strong);
  border-radius:var(--r-pill);
  padding:6px 13px 6px 11px;
  font-size:var(--t-sm);font-weight:500;
  background:var(--surface);
  transition:border-color .15s,background .15s;
}
.chip:hover{border-color:var(--accent);background:color-mix(in oklab, var(--accent) 7%, var(--surface));}
.chip .pin{width:12px;height:12px;stroke:var(--ink-3);fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}
.chip[data-pinned="1"] .pin{stroke:var(--accent);fill:var(--accent);}
.chip .n{font-family:var(--font-mono);font-size:var(--t-xs);color:var(--ink-3);}
.chip.on-list{opacity:.4;pointer-events:none;}

/* ============================================================
   history
   ============================================================ */
.trip{border-bottom:1px solid var(--border);padding:14px 15px;}
.trip:last-child{border-bottom:0;}
.trip-head{display:flex;align-items:baseline;gap:9px;margin-bottom:9px;}
.trip-date{font-family:var(--font-display);font-size:var(--t-md);font-weight:600;}
.trip-ago{font-size:var(--t-xs);color:var(--ink-3);}
.trip-n{margin-left:auto;font-family:var(--font-mono);font-size:var(--t-xs);color:var(--ink-3);}
.trip-items{display:flex;flex-wrap:wrap;gap:6px;}
.trip-item{
  display:inline-flex;align-items:center;gap:6px;
  font-size:var(--t-sm);
  background:var(--surface-2);
  border-radius:var(--r-sm);
  padding:3px 9px 3px 7px;
  color:var(--ink-2);
}
.trip-item i{width:7px;height:7px;border-radius:var(--r-pill);background:var(--person);flex:none;}

/* ============================================================
   calendar
   ============================================================ */
.cal-bar{
  display:flex;align-items:center;gap:9px;
  margin-bottom:12px;flex-wrap:wrap;
}
.cal-nav{display:flex;align-items:center;gap:2px;}
.cal-arrow{
  width:32px;height:32px;border-radius:var(--r-sm);
  display:grid;place-items:center;color:var(--ink-2);
  border:1px solid var(--border);background:var(--surface);
}
.cal-arrow:hover{border-color:var(--border-strong);color:var(--ink);}
.cal-arrow svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.cal-today{
  border:1px solid var(--border);background:var(--surface);
  border-radius:var(--r-sm);padding:6px 12px;
  font-size:var(--t-sm);font-weight:500;color:var(--ink-2);
}
.cal-today:hover{border-color:var(--border-strong);color:var(--ink);}
.cal-title{font-family:var(--font-display);font-size:var(--t-md);font-weight:600;flex:1;min-width:130px;}

.legend{display:flex;flex-wrap:wrap;gap:12px;padding:12px 15px;border-top:1px solid var(--border);}
.legend-item{display:inline-flex;align-items:center;gap:6px;font-size:var(--t-sm);color:var(--ink-2);}
.legend-item i{width:9px;height:9px;border-radius:2px;background:var(--person);}
.cal-note{
  padding:0 15px 13px;font-size:var(--t-xs);color:var(--ink-3);line-height:1.55;
}

.allday{
  display:flex;gap:6px;flex-wrap:wrap;
  padding:11px 15px;border-bottom:1px solid var(--border);
  background:var(--surface-2);
}
.allday-label{font-size:var(--t-xs);color:var(--ink-3);font-weight:600;letter-spacing:.06em;text-transform:uppercase;align-self:center;margin-right:3px;}

.ev{
  border-left:3px solid var(--person);
  background:color-mix(in oklab, var(--person) 13%, var(--surface));
  border-radius:0 var(--r-sm) var(--r-sm) 0;
  padding:4px 8px;
  overflow:hidden;
  display:block;width:100%;
}
.ev:hover{background:color-mix(in oklab, var(--person) 22%, var(--surface));}
.ev-title{display:block;font-size:var(--t-sm);font-weight:500;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.ev-time{display:block;font-family:var(--font-mono);font-size:var(--t-2xs);color:var(--ink-2);letter-spacing:-.01em;}
.allday .ev{width:auto;flex:none;padding:3px 9px;}

.daygrid{position:relative;padding:0 15px 15px 58px;}
.hour{height:54px;position:relative;border-top:1px solid var(--border);}
.hour::before{
  content:attr(data-h);
  position:absolute;left:-46px;top:-8px;
  font-family:var(--font-mono);font-size:var(--t-xs);
  color:var(--ink-3);width:38px;text-align:right;
}
.hour:first-child{border-top:0;}
.day-events{position:absolute;left:58px;right:15px;top:0;bottom:15px;pointer-events:none;}
.day-events .ev{position:absolute;pointer-events:auto;}
.nowline{position:absolute;left:0;right:0;height:1px;background:var(--p-jenn);pointer-events:none;}
.nowline::before{
  content:"";position:absolute;left:-4px;top:-3.5px;
  width:8px;height:8px;border-radius:var(--r-pill);background:var(--p-jenn);
}

.weekscroll{overflow-x:auto;overscroll-behavior-x:contain;}
.week{display:grid;grid-template-columns:44px repeat(7,minmax(104px,1fr));min-width:800px;}
.week-head{
  position:sticky;top:0;z-index:2;
  background:var(--surface);
  border-bottom:1px solid var(--border);
  padding:9px 6px;text-align:center;
}
.week-head .dw{font-size:var(--t-xs);color:var(--ink-3);font-weight:600;letter-spacing:.05em;text-transform:uppercase;}
.week-head .dn{font-family:var(--font-display);font-size:var(--t-md);font-weight:600;line-height:1.2;}
.week-head.is-today .dn{color:var(--accent);}
.week-col{position:relative;border-left:1px solid var(--border);}
.week-gut{position:relative;}
.week-gut .gh{height:42px;position:relative;}
.week-gut .gh::before{
  content:attr(data-h);
  position:absolute;right:7px;top:-7px;
  font-family:var(--font-mono);font-size:var(--t-2xs);color:var(--ink-3);
}
.week-col .wh{height:42px;border-top:1px solid var(--border);}
.week-col .wh:first-child{border-top:0;}
.week-col .ev{position:absolute;left:2px;right:2px;padding:2px 5px;}
.week-col .ev-title{font-size:var(--t-xs);}

.month{display:grid;grid-template-columns:repeat(7,1fr);}
.month-dow{
  text-align:center;padding:9px 2px;
  font-size:var(--t-xs);font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink-3);border-bottom:1px solid var(--border);
}
.mday{
  min-height:82px;
  border-right:1px solid var(--border);
  border-bottom:1px solid var(--border);
  padding:6px 5px;
  display:flex;flex-direction:column;gap:3px;
  align-items:stretch;
}
.mday:nth-child(7n){border-right:0;}
.mday.out{opacity:.35;}
.mday .num{
  font-family:var(--font-mono);font-size:var(--t-xs);color:var(--ink-2);
  align-self:flex-start;
}
.mday.is-today .num{
  background:var(--accent);color:#fff;
  border-radius:var(--r-pill);
  width:20px;height:20px;display:grid;place-items:center;
  font-weight:500;
}
.mev{
  font-size:var(--t-2xs);line-height:1.35;
  border-left:2px solid var(--person);
  padding-left:4px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--ink-2);
}
.mmore{font-size:var(--t-2xs);color:var(--ink-3);font-family:var(--font-mono);}

/* ============================================================
   settings
   ============================================================ */
.srow{
  display:flex;align-items:center;gap:12px;
  padding:13px 15px;border-bottom:1px solid var(--border);
}
.srow:last-child{border-bottom:0;}
.srow-main{flex:1;min-width:0;}
.srow-title{font-weight:500;}
.srow-sub{font-size:var(--t-xs);color:var(--ink-3);margin-top:1px;line-height:1.5;}
.swatch{
  width:30px;height:30px;flex:none;
  border-radius:var(--r-sm);
  background:var(--person);
  border:2px solid var(--surface);
  box-shadow:0 0 0 1px var(--border-strong);
}
.swatch:hover{box-shadow:0 0 0 2px var(--ink-3);}
.feed-input{
  width:100%;
  font-family:var(--font-mono);font-size:var(--t-xs);
  color:var(--ink-2);
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r-sm);
  padding:7px 9px;margin-top:6px;
  overflow:hidden;text-overflow:ellipsis;
}
.feed-input:focus{border-color:var(--accent);}
.toggle{
  width:44px;height:26px;flex:none;
  border-radius:var(--r-pill);
  background:var(--border-strong);
  position:relative;transition:background .18s;
}
.toggle::after{
  content:"";position:absolute;top:3px;left:3px;
  width:20px;height:20px;border-radius:var(--r-pill);
  background:var(--surface);transition:transform .18s;
  box-shadow:var(--shadow-sm);
}
.toggle[aria-pressed="true"]{background:var(--accent);}
.toggle[aria-pressed="true"]::after{transform:translateX(18px);}

.btn-quiet{
  border:1px solid var(--border-strong);
  border-radius:var(--r-sm);
  padding:8px 15px;
  font-size:var(--t-sm);font-weight:500;color:var(--ink-2);
  background:var(--surface);
}
.btn-quiet:hover{border-color:var(--ink-3);color:var(--ink);}

/* ============================================================
   coming-soon placeholder
   ============================================================ */
.soon{
  padding:44px 24px;text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:13px;
}
.soon svg{width:34px;height:34px;stroke:var(--ink-3);fill:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
.soon h2{font-size:var(--t-lg);font-weight:600;}
.soon p{max-width:42ch;color:var(--ink-2);margin:0;font-size:var(--t-sm);line-height:1.65;}
.soon .eyebrow{margin-bottom:-6px;}

/* ============================================================
   sheet / popover / toast
   ============================================================ */
.scrim{
  position:fixed;inset:0;z-index:60;
  background:rgba(16,20,16,.42);
  display:flex;align-items:flex-end;justify-content:center;
  animation:fade .18s ease;
}
@keyframes fade{from{opacity:0}to{opacity:1}}
.sheet{
  width:100%;max-width:520px;
  background:var(--surface);
  border:1px solid var(--border);
  border-bottom:0;
  border-radius:14px 14px 0 0;
  box-shadow:var(--shadow-lg);
  padding-bottom:env(safe-area-inset-bottom);
  max-height:88vh;overflow-y:auto;
  animation:rise .22s cubic-bezier(.2,.7,.3,1);
}
@keyframes rise{from{transform:translateY(18px);opacity:.6}to{transform:translateY(0);opacity:1}}
.sheet-grip{width:34px;height:4px;border-radius:var(--r-pill);background:var(--border-strong);margin:9px auto 4px;}
.sheet-head{padding:10px 18px 14px;border-bottom:1px solid var(--border);}
.sheet-head h3{font-size:var(--t-lg);font-weight:600;line-height:1.2;}
.sheet-head .sub{font-size:var(--t-sm);color:var(--ink-3);margin-top:3px;}
.sheet-head .sub b{color:var(--person);font-weight:600;}
.sheet-body{padding:16px 18px;display:flex;flex-direction:column;gap:17px;}
.field label{display:block;margin-bottom:7px;}
.field input[type="text"]{
  width:100%;
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r-sm);
  padding:10px 11px;
}
.field input[type="text"]:focus{border-color:var(--accent);}
.opts{display:flex;flex-wrap:wrap;gap:6px;}
.opt{
  border:1px solid var(--border-strong);
  border-radius:var(--r-pill);
  padding:6px 13px;
  font-size:var(--t-sm);font-weight:500;color:var(--ink-2);
}
.opt[aria-pressed="true"]{
  background:var(--accent);border-color:var(--accent);color:#fff;
}
.hint{font-size:var(--t-xs);color:var(--ink-3);line-height:1.55;margin-top:7px;}
.hint b{color:var(--ink-2);font-weight:600;}
.sheet-foot{
  display:flex;gap:9px;align-items:center;
  padding:13px 18px 18px;border-top:1px solid var(--border);
}
.sheet-foot .grow{flex:1;}
.btn-danger{color:var(--p-jenn);font-size:var(--t-sm);font-weight:500;padding:8px 12px;border-radius:var(--r-sm);}
.btn-danger:hover{background:color-mix(in oklab, var(--p-jenn) 12%, transparent);}
.btn-primary{
  background:var(--accent);color:#fff;
  border-radius:var(--r-sm);padding:10px 20px;
  font-size:var(--t-sm);font-weight:600;
}

.pop{
  position:absolute;z-index:50;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r);
  box-shadow:var(--shadow-lg);
  padding:5px;min-width:212px;
  animation:fade .13s ease;
}
.pop-label{
  font-size:var(--t-xs);color:var(--ink-3);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;
  padding:8px 11px 6px;
}
.pop-item{
  display:flex;align-items:center;gap:10px;
  width:100%;padding:9px 11px;border-radius:var(--r-sm);
  font-size:var(--t-sm);
}
.pop-item:hover{background:var(--surface-2);}
.pop-item i{width:11px;height:11px;border-radius:var(--r-pill);background:var(--person);flex:none;}
.pop-item .grow{flex:1;}
.pop-item .tick{width:14px;height:14px;stroke:var(--accent);fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;}
.pop-note{
  font-size:var(--t-2xs);color:var(--ink-3);line-height:1.5;
  padding:7px 11px 8px;border-top:1px solid var(--border);margin-top:4px;
}
.pal{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;padding:8px;}
.pal button{width:32px;height:32px;border-radius:var(--r-sm);box-shadow:0 0 0 1px var(--border-strong) inset;}
.pal button:hover{transform:scale(1.08);}

.toast{
  position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(var(--tabbar-h) + 104px + env(safe-area-inset-bottom));
  z-index:70;
  background:var(--ink);color:var(--bg);
  border-radius:var(--r-pill);
  padding:9px 18px;font-size:var(--t-sm);font-weight:500;
  box-shadow:var(--shadow-lg);
  animation:rise .2s cubic-bezier(.2,.7,.3,1);
  white-space:nowrap;
}

/* ============================================================
   desktop — sidebar + two-pane grocery
   ============================================================ */
@media (min-width:900px){
  .sidebar{
    display:flex;flex-direction:column;
    width:var(--sidebar-w);flex:none;
    background:var(--surface);
    border-right:1px solid var(--border);
    padding:20px 12px 14px;
    gap:22px;
  }
  .sidebar .wordmark{font-size:var(--t-xl);padding:0 10px;}
  .sidenav{display:flex;flex-direction:column;gap:2px;}
  .sidenav button{
    display:flex;align-items:center;gap:11px;
    padding:9px 11px;border-radius:var(--r-sm);
    font-size:var(--t-sm);font-weight:500;color:var(--ink-2);
    transition:background .15s,color .15s;
  }
  .sidenav button svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:none;}
  .sidenav button:hover{background:var(--surface-2);color:var(--ink);}
  .sidenav button[aria-current="page"]{
    background:color-mix(in oklab, var(--accent) 12%, var(--surface));
    color:var(--accent);font-weight:600;
  }
  .sidenav button[data-soon="1"]{opacity:.45;}
  .sidenav .soonlabel{
    margin-left:auto;font-size:var(--t-3xs);font-weight:600;letter-spacing:.07em;
    text-transform:uppercase;color:var(--ink-3);
  }
  .side-foot{margin-top:auto;padding:0 4px;}

  .tabbar{display:none;}
  .topbar{padding:14px 22px;background:transparent;border-bottom:1px solid var(--border);}
  .content,.content.no-compose{padding-bottom:56px;}
  .screen{padding:22px 22px 0;}
  .composer{
    position:static;
    padding:14px 22px calc(14px + env(safe-area-inset-bottom));
  }
  .composer-inner{max-width:1200px;margin:0 auto;}
  .toast{bottom:34px;}
  .scrim{align-items:center;}
  .sheet{
    border-radius:14px;border-bottom:1px solid var(--border);
    max-width:460px;
  }
  .sheet-grip{display:none;}
  .sheet-head{padding-top:18px;}

  .two-pane{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:16px;align-items:start;}
  .rail{display:flex;flex-direction:column;gap:14px;}
  .mobile-only{display:none !important;}
  .mday{min-height:104px;}
  .week{min-width:0;}
}
@media (max-width:899px){
  .two-pane .rail{display:none;}
}

/* ============================================================
   Additions for the live app — states the mockup had no need for
   ============================================================ */

/* Boot: the shell paints before data arrives. */
.booting{
  height:100%;display:flex;align-items:center;justify-content:center;
  color:var(--ink-3);font-size:var(--t-sm);gap:10px;
}
.spinner{
  width:15px;height:15px;flex:none;
  border:2px solid var(--border-strong);
  border-top-color:var(--accent);
  border-radius:var(--r-pill);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

/* The network pill gains two more states once there is a real queue. */
.netpill[data-state="syncing"] i{background:var(--p-tavi);animation:blip 1s ease-in-out infinite;}
.netpill[data-state="error"] i{background:var(--p-jenn);}
.netpill .qn{
  font-family:var(--font-mono);font-size:var(--t-2xs);
  background:var(--ink);color:var(--bg);
  border-radius:var(--r-pill);padding:0 5px;margin-left:2px;
}

.errbar{
  flex:none;
  background:color-mix(in oklab, var(--p-jenn) 16%, var(--surface));
  border-bottom:1px solid color-mix(in oklab, var(--p-jenn) 40%, var(--border));
  color:var(--ink);
  font-size:var(--t-sm);
  padding:9px 16px;display:flex;align-items:center;gap:10px;
}
.errbar .grow{flex:1;}
.errbar button{
  font-size:var(--t-xs);font-weight:600;color:var(--p-jenn);
  padding:3px 9px;border-radius:var(--r-sm);
  border:1px solid color-mix(in oklab, var(--p-jenn) 45%, transparent);
}

/* Sign-in errors come back as ?error=… from the OAuth callback. */
.signin-error{
  max-width:38ch;
  background:color-mix(in oklab, var(--p-jenn) 13%, var(--surface));
  border:1px solid color-mix(in oklab, var(--p-jenn) 38%, var(--border));
  border-radius:var(--r);
  padding:12px 15px;font-size:var(--t-sm);line-height:1.55;text-align:left;
}
.signin-error b{display:block;margin-bottom:3px;}

/* Calendar feed health, shown in Settings. */
.feed-state{
  display:inline-flex;align-items:center;gap:6px;
  font-size:var(--t-xs);color:var(--ink-3);margin-top:6px;
}
.feed-state i{width:7px;height:7px;border-radius:var(--r-pill);background:var(--ink-3);flex:none;}
.feed-state[data-ok="1"] i{background:var(--p-flynn);}
.feed-state[data-ok="0"] i{background:var(--p-jenn);}
.feed-state[data-ok="0"]{color:var(--p-jenn);}

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

/* An item another device just changed gets a brief highlight so a list
   that rearranges itself under your thumb is not disorienting. */
@keyframes flashIn{
  from{background:color-mix(in oklab, var(--person) 22%, var(--surface));}
  to{background:transparent;}
}
.row.flash{animation:flashIn 1.4s ease-out;}

.offline-hint{
  font-size:var(--t-xs);color:var(--ink-3);
  padding:10px 15px;border-top:1px solid var(--border);line-height:1.55;
}

/* ============================================================
   To-do
   ============================================================ */

/* Who a todo is for, chosen while adding it. */
.todo-composer{
  position:absolute;left:0;right:0;
  bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  z-index:25;
  background:var(--surface);
  border-top:1px solid var(--border);
  padding:10px 12px;
  display:flex;flex-direction:column;gap:8px;
}
.todo-composer .line{display:flex;gap:8px;align-items:center;}
.todo-composer .grow{flex:1;min-width:0;}

.pill-select{
  display:inline-flex;align-items:center;gap:7px;
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r);
  padding:0 10px;
  min-width:0;
}
.pill-select:focus-within{border-color:var(--accent);}
.pill-select i{
  width:9px;height:9px;border-radius:var(--r-pill);
  background:var(--person,var(--ink-3));flex:none;
}
.pill-select select,
.pill-select input{
  border:0;background:none;
  padding:10px 0;font-size:var(--t-sm);
  min-width:0;max-width:100%;
  color:var(--ink);
  appearance:none;
}
.pill-select select{padding-right:14px;}
.pill-select .cal{width:15px;height:15px;stroke:var(--ink-3);fill:none;stroke-width:1.8;flex:none;}

/* A todo row reuses the grocery row, with the assignee's colour on the
   checkbox and the extra detail in the meta line. */
.todo-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:2px;}
.due{
  display:inline-flex;align-items:center;gap:4px;
  font-family:var(--font-mono);font-size:var(--t-2xs);
  border:1px solid var(--border-strong);
  border-radius:var(--r-sm);
  padding:1px 6px;color:var(--ink-2);
}
.due[data-when="today"]{border-color:var(--p-tavi);color:var(--p-tavi);font-weight:500;}
.due[data-when="overdue"]{border-color:var(--p-jenn);color:var(--p-jenn);font-weight:500;}
.due[data-when="soon"]{border-color:var(--border-strong);color:var(--ink-2);}

.for-who{font-weight:600;color:var(--person);}

/* Parent's person filter. */
.who-bar{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px;}
.who-chip{
  display:inline-flex;align-items:center;gap:7px;
  border:1px solid var(--border-strong);
  border-radius:var(--r-pill);
  padding:6px 13px;
  font-size:var(--t-sm);font-weight:500;
  color:var(--ink-2);background:var(--surface);
  transition:border-color .15s,color .15s,background .15s;
}
.who-chip i{width:9px;height:9px;border-radius:var(--r-pill);background:var(--person,var(--ink-3));flex:none;}
.who-chip .n{
  font-family:var(--font-mono);font-size:var(--t-xs);
  color:var(--ink-3);
}
.who-chip[aria-pressed="true"]{
  border-color:var(--person,var(--accent));
  color:var(--person,var(--accent));
  background:color-mix(in oklab, var(--person, var(--accent)) 10%, var(--surface));
}
.who-chip[aria-pressed="true"] .n{color:inherit;opacity:.75;}

/* Read-only rows: a child may tick their own items but not reword one a
   parent set, so the affordance has to be absent, not just refused. */
.row.locked .row-open{display:none;}
.check[disabled]{opacity:.4;cursor:not-allowed;}
.check[disabled]:hover{background:none;}

/* Todos with a due date appear on the calendar; mark them so they do not
   read as real events. */
.ev.is-todo{
  border-left-style:dashed;
  background:color-mix(in oklab, var(--person) 8%, var(--surface));
}
.ev.is-todo .ev-title::before{
  content:"";
  display:inline-block;
  width:9px;height:9px;
  margin-right:5px;
  border:1.5px solid var(--person);
  border-radius:2px;
  vertical-align:-1px;
}

/* ============================================================
   Calendar feeds in Settings
   ============================================================ */
.feed-row{
  display:flex;align-items:center;gap:10px;
  padding:9px 0;
  border-top:1px solid var(--border);
}
.feed-row:first-of-type{border-top:0;}
.feed-main{flex:1;min-width:0;}
.feed-label{font-size:var(--t-sm);font-weight:500;}
.feed-actions{display:flex;gap:4px;flex:none;}
.icon-btn{
  width:28px;height:28px;border-radius:var(--r-sm);
  display:grid;place-items:center;color:var(--ink-3);
  border:1px solid transparent;
}
.icon-btn:hover{background:var(--surface-2);color:var(--ink);border-color:var(--border);}
.icon-btn svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}
.icon-btn[data-danger="1"]:hover{color:var(--p-jenn);border-color:color-mix(in oklab, var(--p-jenn) 40%, transparent);}

.add-feed{display:flex;flex-direction:column;gap:7px;padding-top:10px;border-top:1px solid var(--border);}
.add-feed .line{display:flex;gap:7px;}
.add-feed input{
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r-sm);
  padding:8px 9px;font-size:var(--t-sm);
  min-width:0;
}
.add-feed input:focus{border-color:var(--accent);}
.add-feed .label-input{width:34%;flex:none;}
.add-feed .url-input{flex:1;font-family:var(--font-mono);font-size:var(--t-xs);}

@media (min-width:900px){
  .todo-composer{
    position:static;
    border-top:0;border-bottom:1px solid var(--border);
    padding:14px 22px calc(14px + env(safe-area-inset-bottom));
    background:transparent;
  }
  .todo-composer .inner{max-width:1200px;margin:0 auto;display:flex;flex-direction:column;gap:8px;width:100%;}
}

/* ============================================================
   Bubble tracker
   ============================================================ */
.lockpill{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-xs);font-weight:600;color:var(--ink-3);
  border:1px solid var(--border);background:var(--surface-2);
  border-radius:var(--r-pill);padding:3px 9px 3px 7px;
}
.lockpill svg{width:11px;height:11px;stroke:currentColor;fill:none;stroke-width:2;}

/* The streak is not one of the activities, so it must not sit in the row
   looking like one — four numbers for three activities, the first in
   plain ink, reads as an activity coloured black. A rule separates them,
   and each count carries its ring's colour as a dot. */
.streak{display:flex;align-items:center;gap:14px;padding:12px 15px;border-bottom:1px solid var(--border);flex-wrap:wrap;}
.stat-sep{width:1px;align-self:stretch;min-height:30px;background:var(--border);flex:none;}
.stat-counts{display:flex;gap:16px;flex-wrap:wrap;min-width:0;}
.stat .n{font-family:var(--font-display);font-size:var(--t-lg);font-weight:700;line-height:1;}
.stat .l{
  display:flex;align-items:center;gap:5px;
  font-size:var(--t-2xs);color:var(--ink-3);letter-spacing:.04em;
  text-transform:uppercase;font-weight:600;margin-top:4px;
}
.stat .dot{
  width:7px;height:7px;border-radius:var(--r-pill);
  background:var(--act);flex:none;
}
.stat-streak .n{color:var(--ink-2);}

.cal-bubbles{padding:12px 12px 14px;}
.bgrid{display:grid;grid-template-columns:22px repeat(7,1fr);gap:5px;align-items:center;}
.bgrid .dow{
  text-align:center;font-size:var(--t-2xs);font-weight:600;
  color:var(--ink-3);letter-spacing:.04em;padding-bottom:2px;
}
.bgrid .mlabel{
  font-family:var(--font-mono);font-size:var(--t-3xs);color:var(--ink-3);
  text-align:right;padding-right:2px;line-height:1;
}
.bcell{display:grid;place-items:center;}

/* Concentric bands from layered inset shadows: the first is painted on
   top, so slot 1 owns the outer ring, slot 2 the middle, slot 3 the
   centre. A skipped slot falls back to the surface colour, never to
   transparent — transparent does not mask the layer beneath, so an inner
   ring would bleed outward and fill the gap it is meant to leave.
   Band widths follow how many activities exist, so tracking one thing
   gives a solid disc rather than a thin donut. */
.bub{
  /* Never wider than its column. A fixed 32px × scale overflows the
     seven-column grid on a phone once the text size is turned up. */
  width:min(var(--bub), 100%);
  aspect-ratio:1;
  height:auto;
  border-radius:50%;
  background-color:var(--surface);
  border:1px solid var(--border);
  transition:transform .12s ease;
  position:relative;
}

/* A day with nothing logged shows its date, so a run of empty bubbles is
   still navigable and today is identifiable at a glance. Days with rings
   have no room for it and do not need one — the rings are the signal. */
.bub .num{
  position:absolute;inset:0;
  display:grid;place-items:center;
  font-family:var(--font-mono);
  font-size:var(--t-2xs);
  color:var(--ink-3);
  pointer-events:none;
  letter-spacing:-.02em;
}
.bcell[data-today="1"] .bub .num{color:var(--ink);font-weight:500;}
/* Rings as percentage gradient stops rather than pixel shadows, so they
   stay proportional at whatever size the bubble settles at. The outermost
   band is slot 1, the centre slot 3. A skipped slot paints the surface
   colour — that is what reserves its position, rather than letting the
   ring inside it bleed outward and fill the gap. */
.bub[data-n="1"]{
  background-image:radial-gradient(circle closest-side at center,
    var(--r1, var(--surface)) 0 100%);
}
.bub[data-n="2"]{
  background-image:radial-gradient(circle closest-side at center,
    var(--r2, var(--surface)) 0 56.25%,
    var(--r1, var(--surface)) 56.25% 100%);
}
.bub[data-n="3"]{
  background-image:radial-gradient(circle closest-side at center,
    var(--r3, var(--surface)) 0 37.5%,
    var(--r2, var(--surface)) 37.5% 68.75%,
    var(--r1, var(--surface)) 68.75% 100%);
}
.bub:hover{transform:scale(1.12);}
.bub:active{transform:scale(.94);}
.bub[data-empty="1"]{border-style:dashed;border-color:var(--border-strong);}
.bub[data-future="1"]{opacity:.28;pointer-events:none;border-style:solid;}
.bcell[data-today="1"] .bub{outline:2px solid var(--ink);outline-offset:2px;}
.bcell[data-sel="1"] .bub{outline:2px solid var(--accent);outline-offset:2px;}

.day-head{display:flex;align-items:baseline;gap:8px;padding:12px 15px 8px;}
.day-head h3{font-family:var(--font-display);font-size:var(--t-md);font-weight:600;}
.day-head .ago{font-size:var(--t-xs);color:var(--ink-3);}
.day-head .grow{flex:1;}

.tog{
  display:flex;align-items:center;gap:11px;width:100%;
  padding:11px 15px;border-top:1px solid var(--border);
}
.tog:hover{background:var(--surface-2);}
.tog .ring{
  width:calc(26px * var(--fs));aspect-ratio:1;height:auto;
  border-radius:50%;flex:none;
  background-color:var(--surface);border:1px solid var(--border);
}
.tog .ring[data-n="1"]{
  background-image:radial-gradient(circle closest-side at center, var(--r1, var(--surface)) 0 100%);
}
.tog .ring[data-n="2"]{
  background-image:radial-gradient(circle closest-side at center,
    var(--r2, var(--surface)) 0 56.25%, var(--r1, var(--surface)) 56.25% 100%);
}
.tog .ring[data-n="3"]{
  background-image:radial-gradient(circle closest-side at center,
    var(--r3, var(--surface)) 0 37.5%,
    var(--r2, var(--surface)) 37.5% 68.75%,
    var(--r1, var(--surface)) 68.75% 100%);
}
.tog .nm{flex:1;font-size:var(--t-sm);font-weight:500;}
.tog[aria-pressed="false"] .nm{color:var(--ink-3);font-weight:400;}
.tog .slot{font-family:var(--font-mono);font-size:var(--t-2xs);color:var(--ink-3);}
.sw{
  width:40px;height:24px;border-radius:var(--r-pill);
  background:var(--border-strong);position:relative;flex:none;transition:background .18s;
}
.sw::after{
  content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;
  border-radius:var(--r-pill);background:var(--surface);
  box-shadow:var(--shadow-sm);transition:transform .18s;
}
.tog[aria-pressed="true"] .sw{background:var(--act);}
.tog[aria-pressed="true"] .sw::after{transform:translateX(16px);}

.act-row{display:flex;align-items:center;gap:9px;padding:10px 15px;border-top:1px solid var(--border);}
.act-row:first-of-type{border-top:0;}
.act-row .slotn{font-family:var(--font-mono);font-size:var(--t-2xs);color:var(--ink-3);width:38px;flex:none;}
.act-row .swatch{
  width:26px;height:26px;border-radius:var(--r-sm);flex:none;
  background:var(--act);border:2px solid var(--surface);
  box-shadow:0 0 0 1px var(--border-strong);
}
.act-row .swatch:hover{box-shadow:0 0 0 2px var(--ink-3);}
.act-row input{
  flex:1;min-width:0;background:var(--surface-2);
  border:1px solid var(--border);border-radius:var(--r-sm);
  padding:7px 9px;font-size:var(--t-sm);
}
.act-row input:focus{outline:none;border-color:var(--accent);}

.addact{
  display:flex;align-items:center;gap:8px;width:100%;
  padding:12px 15px;border-top:1px solid var(--border);
  font-size:var(--t-sm);font-weight:500;color:var(--accent);
}
.addact:hover{background:var(--surface-2);}
.addact svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;}

/* ============================================================
   Text size control
   ============================================================ */
.fs-controls{
  display:flex;align-items:center;gap:4px;flex:none;
  border:1px solid var(--border-strong);
  border-radius:var(--r);
  background:var(--surface);
  padding:3px;
}
.fs-btn{
  width:38px;height:34px;flex:none;
  display:grid;place-items:center;
  border-radius:var(--r-sm);
  font-family:var(--font-display);
  font-weight:600;
  color:var(--ink-2);
  line-height:1;
}
.fs-btn:hover:not(:disabled){background:var(--surface-2);color:var(--ink);}
.fs-btn:disabled{opacity:.3;cursor:not-allowed;}
.fs-btn .small{font-size:12px;}
.fs-btn .big{font-size:18px;}
.fs-now{
  min-width:52px;text-align:center;
  font-size:var(--t-sm);color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
.fs-sample{
  margin-top:10px;padding:11px 13px;
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:var(--r-sm);
  color:var(--ink-2);
  font-size:var(--t-base);
  line-height:1.5;
}
.fs-sample b{color:var(--ink);font-weight:600;}

/* The legend doubles as a per-device visibility filter — tap a name to
   drop that calendar out of every view. Hidden reads as a hollow dot and
   faded text, so it is obviously off rather than simply absent. */
.legend-item{
  cursor:pointer;
  border:0;
  padding:2px 0;
  transition:opacity .15s;
}
.legend-item[aria-pressed="false"]{opacity:.4;}
.legend-item[aria-pressed="false"] i{
  background:transparent;
  box-shadow:inset 0 0 0 1.5px var(--person);
}
.legend-item:hover{opacity:1;}
.legend-item:hover i{outline:2px solid var(--person);outline-offset:2px;}
