/* ============================================================
   bBoard — design system
   ============================================================ */
:root{
  color-scheme: light dark;

  /* surfaces */
  --bg:#f4f6f8;
  --surface:#ffffff;
  --surface-2:#f7f9fa;
  --sunken:#eef1f4;
  --line:#e2e7ec;
  --line-strong:#cdd5dd;

  /* ink */
  --ink:#0f1720;
  --ink-2:#43535f;
  --ink-3:#7b8894;

  /* accents */
  --brand:#0d9488;
  --brand-ink:#ffffff;
  --brand-soft:rgba(13,148,136,.10);
  --danger:#dc2626;
  --danger-soft:rgba(220,38,38,.10);
  --ok:#15803d;
  --ok-soft:rgba(21,128,61,.10);

  /* shape */
  --r-lg:18px; --r-md:13px; --r-sm:10px;
  --sh-1:0 1px 2px rgba(13,25,38,.06), 0 1px 3px rgba(13,25,38,.05);
  --sh-2:0 4px 12px rgba(13,25,38,.08), 0 1px 3px rgba(13,25,38,.05);
  --sh-3:0 18px 48px rgba(9,18,28,.20), 0 2px 8px rgba(9,18,28,.10);

  --ease:cubic-bezier(.2,.8,.3,1);

  /* top-bar chrome: buttons, avatar ring, deck arrows/dots — black in
     light mode, bright white in dark mode, independent of --ink */
  --chrome:#000000;
}

/* Dark tokens apply when the OS asks for dark and the user has not forced
   light, or when the user has explicitly chosen dark. The nutrition label is
   immune either way — it paints from its own --lbg/--ltext variables. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --bg:#0d1116;
    --surface:#161c23;
    --surface-2:#1b222b;
    --sunken:#11171d;
    --line:#262f3a;
    --line-strong:#36414f;
    --ink:#e9eef3;
    --ink-2:#a9b6c2;
    --ink-3:#78889a;
    --brand:#14b8a6;
    --brand-ink:#03201d;
    --brand-soft:rgba(20,184,166,.14);
    --danger:#f87171;
    --danger-soft:rgba(248,113,113,.14);
    --ok:#4ade80;
    --ok-soft:rgba(74,222,128,.14);
    --sh-1:0 1px 2px rgba(0,0,0,.4);
    --sh-2:0 4px 14px rgba(0,0,0,.45);
    --sh-3:0 22px 60px rgba(0,0,0,.62);
    --chrome:#ffffff;
  }
}

:root[data-theme="dark"]{
    --bg:#0d1116;
    --surface:#161c23;
    --surface-2:#1b222b;
    --sunken:#11171d;
    --line:#262f3a;
    --line-strong:#36414f;
    --ink:#e9eef3;
    --ink-2:#a9b6c2;
    --ink-3:#78889a;
    --brand:#14b8a6;
    --brand-ink:#03201d;
    --brand-soft:rgba(20,184,166,.14);
    --danger:#f87171;
    --danger-soft:rgba(248,113,113,.14);
    --ok:#4ade80;
    --ok-soft:rgba(74,222,128,.14);
    --sh-1:0 1px 2px rgba(0,0,0,.4);
    --sh-2:0 4px 14px rgba(0,0,0,.45);
    --sh-3:0 22px 60px rgba(0,0,0,.62);
    --chrome:#ffffff;
  }
:root[data-theme="light"]{color-scheme:light; --chrome:#000000}
:root[data-theme="dark"]{color-scheme:dark}


*{box-sizing:border-box}
/* number inputs: no spinners anywhere — they crowd the value and nobody
   nudges a calorie count one at a time */
input[type=number]{-moz-appearance:textfield; appearance:textfield}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none; margin:0}
html,body{margin:0;padding:0}
body{
  font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif;
  background:var(--bg); color:var(--ink);
  -webkit-text-size-adjust:100%;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--brand); text-decoration:none}
a:hover{text-decoration:underline}
button{font:inherit; color:inherit}
input,select,textarea{font:inherit; color:inherit}
h1,h2,h3{letter-spacing:-.02em}

/* ---------------- controls ---------------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:10px 15px; border:1px solid var(--line-strong); border-radius:var(--r-md);
  background:var(--surface); cursor:pointer; font-weight:600; font-size:14px;
  box-shadow:var(--sh-1); transition:transform .12s var(--ease), border-color .12s, background .12s;
}
.btn:hover{border-color:var(--brand); transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
.btn-primary{background:var(--brand); border-color:transparent; color:var(--brand-ink)}
.btn-primary:hover{border-color:transparent; filter:brightness(1.06)}
.btn-ghost{background:transparent; border-color:transparent; box-shadow:none}
.btn-ghost:hover{background:var(--surface-2); border-color:var(--line)}
.btn-danger{background:transparent; border-color:var(--line-strong); color:var(--danger)}
.btn-danger:hover{border-color:var(--danger); background:var(--danger-soft)}
.btn-sm{padding:6px 11px; font-size:13px; border-radius:var(--r-sm)}
.btn-block{width:100%}
.btn:disabled{opacity:.5; cursor:not-allowed; transform:none}
:focus-visible{outline:2px solid var(--brand); outline-offset:2px; border-radius:6px}

.field{display:grid; gap:6px; font-size:12px; font-weight:650; color:var(--ink-2);
  letter-spacing:.01em; min-width:0}
.field > input,.field > select,.field > textarea{
  padding:10px 12px; border:1px solid var(--line-strong); border-radius:var(--r-sm);
  background:var(--sunken); width:100%; font-weight:500; font-size:14px; color:var(--ink);
  transition:border-color .12s, background .12s;
}
.field > input:focus,.field > select:focus,.field > textarea:focus{
  outline:none; border-color:var(--brand); background:var(--surface);
  box-shadow:0 0 0 3px var(--brand-soft);
}
.field textarea{min-height:78px; resize:vertical; line-height:1.5}
.field small{font-weight:450; font-size:11.5px; color:var(--ink-3)}
.grid2{display:grid; grid-template-columns:1fr 1fr; gap:11px}

/* dense number entry — the unit tag sits inside the box, no label row above */
.numgrid{display:grid; grid-template-columns:repeat(3,1fr); gap:6px}
.numcell{display:flex; align-items:center; gap:6px; min-width:0;
  padding:0 9px; border:1px solid var(--line-strong); border-radius:8px;
  background:var(--sunken); transition:border-color .12s, background .12s}
/* the tag is only as wide as its own text — "Cal" no longer reserves the
   same gutter as "Sodium mg" */
.numcell b{
  flex:0 0 auto; font-size:10.5px; font-weight:500; color:var(--ink-3);
  pointer-events:none; white-space:nowrap; letter-spacing:.01em;
}
.numcell input{
  flex:1 1 auto; min-width:0; padding:8px 0; border:0; background:none;
  font-size:13px; font-weight:650; font-variant-numeric:tabular-nums;
  text-align:right; color:var(--ink);
}
.numcell input::placeholder{font-weight:500; color:var(--ink-3); opacity:.55}
.numcell input:focus{outline:none}
.numcell:focus-within{border-color:var(--brand); background:var(--surface);
  box-shadow:0 0 0 2px var(--brand-soft)}
.numcell:focus-within b{color:var(--brand)}
@media (max-width:400px){ .numgrid{grid-template-columns:repeat(2,1fr)} }

/* the name / meal / servings header row of the Add Food sheet */
.entryhead{display:grid; grid-template-columns:1fr auto 4.6em; gap:6px}
.entryhead > input,.entryhead > select{
  padding:8px 10px; border:1px solid var(--line-strong); border-radius:9px;
  background:var(--sunken); font-size:13.5px; font-weight:600; min-width:0; width:100%;
}
.entryhead > input[type=number]{text-align:right; font-variant-numeric:tabular-nums}
.entryhead > *:focus{outline:none; border-color:var(--brand); background:var(--surface);
  box-shadow:0 0 0 2px var(--brand-soft)}
.entryhead ::placeholder{font-weight:500; color:var(--ink-3); opacity:1}
@media (max-width:400px){
  .entryhead{grid-template-columns:1fr 1fr}
  .entryhead > input:first-child{grid-column:1/-1}
}

.switch{display:flex; align-items:center; gap:10px; font-weight:600; font-size:14px;
  cursor:pointer; color:var(--ink); padding:9px 11px; border:1px solid var(--line);
  border-radius:var(--r-sm); background:var(--sunken)}
.switch:hover{border-color:var(--line-strong)}
.switch input{width:17px; height:17px; accent-color:var(--brand); flex:0 0 auto}

.pill{display:inline-flex; align-items:center; gap:4px; font-size:10.5px; font-weight:750;
  letter-spacing:.05em; padding:3px 8px; border-radius:999px; text-transform:uppercase;
  border:1px solid transparent}
.pill.pub{color:var(--ok); background:var(--ok-soft); border-color:color-mix(in srgb,var(--ok) 30%,transparent)}
.pill.priv{color:var(--danger); background:var(--danger-soft); border-color:color-mix(in srgb,var(--danger) 30%,transparent)}

.muted{color:var(--ink-3); font-size:12.5px}
.alert{padding:10px 12px; border-radius:var(--r-sm); font-size:13.5px; margin-bottom:11px;
  border:1px solid transparent}
.alert-err{background:var(--danger-soft); border-color:color-mix(in srgb,var(--danger) 32%,transparent); color:var(--danger)}
.alert-ok{background:var(--ok-soft); border-color:color-mix(in srgb,var(--ok) 32%,transparent); color:var(--ok)}

/* ============================================================
   Auth pages
   ============================================================ */
.authbody{display:grid; place-items:center; min-height:100dvh; padding:24px 14px}
.authwrap{width:100%; max-width:400px}
.authcard{background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); box-shadow:var(--sh-3); padding:28px 26px 24px}
.authbrand{text-align:center; margin-bottom:20px}
.authbrand-mark{display:block; font-size:25px; font-weight:800; letter-spacing:-.035em}
.authbrand-sub{display:block; font-size:12.5px; color:var(--ink-3); margin-top:3px}
.authtitle{margin:0 0 3px; font-size:18px}
.authsub{margin:0 0 14px; color:var(--ink-3); font-size:13.5px}
.authform{display:grid; gap:13px; margin-top:14px}
.authform label{display:grid; gap:6px; font-size:12px; font-weight:650; color:var(--ink-2)}
.authform input{padding:11px 12px; border:1px solid var(--line-strong); border-radius:var(--r-sm);
  background:var(--sunken); width:100%; font-size:14.5px}
.authform input:focus{outline:none; border-color:var(--brand); background:var(--surface);
  box-shadow:0 0 0 3px var(--brand-soft)}
.authform small{font-weight:450; font-size:11.5px; color:var(--ink-3)}
.authform .btn{margin-top:4px; padding:12px}
.authfoot{margin-top:18px; text-align:center; font-size:13px; color:var(--ink-3)}

/* ============================================================
   The nutrition label
   Sizes are em-based so `.label.sm` scales the whole thing.
   ============================================================ */
.label{
  --lbg:#fff; --lborder:#000; --ltext:#000; --laccent:#c0392b;
  --lfont:"Helvetica Neue",Helvetica,Arial,sans-serif;
  font-size:15px;                      /* the scale knob */
  background:var(--lbg); color:var(--ltext); font-family:var(--lfont);
  border:0.14em solid var(--lborder); border-radius:6px;
  padding:0.7em 0.85em 0.8em; width:100%;
  transition:background .15s, color .15s, border-color .15s;
}
.label.sm{font-size:12.6px}            /* ~15% smaller */
.label-head{display:flex; align-items:flex-start; justify-content:space-between; gap:.5em}
.label-title{font-size:1.85em; font-weight:900; letter-spacing:-.03em; line-height:1.04;
  margin:0; color:var(--ltitle, var(--ltext)); font-family:var(--ltitlefont, var(--lfont))}
.label-sub{font-size:.76em; opacity:.72; margin:.15em 0 0; font-weight:500}
.label-datebtn{display:inline-block; padding:0; border:0; background:none; cursor:pointer;
  color:inherit; font-family:inherit; text-align:left; border-radius:4px;
  text-decoration:underline dotted; text-underline-offset:.2em}
.label-datebtn:hover{opacity:1}

.rule{border:0; height:1px; background:currentColor; margin:.35em 0; opacity:1}
.rule-thick{height:.6em; margin:.28em 0}
.rule-mid{height:.27em; margin:.28em 0}

.cal-row{display:grid; grid-template-columns:1fr auto auto; align-items:baseline; gap:0 .7em}
.colhead{font-size:.8em; font-weight:700; text-align:right; padding-bottom:.1em}
.cal-word{font-size:1.5em; font-weight:900; letter-spacing:-.02em}
.cal-num{font-size:1.5em; font-weight:900; text-align:right; min-width:2.9em;
  font-variant-numeric:tabular-nums}
.cal-goal{font-size:1em; font-weight:700; text-align:right; min-width:4.3em; opacity:.72;
  font-variant-numeric:tabular-nums}

.headrow,.nrow{display:grid; grid-template-columns:1fr 4.2em 4.2em 3.6em; gap:0 .45em}
.headrow{font-size:.73em; font-weight:700; text-align:right; padding-bottom:.2em;
  white-space:nowrap}
.headrow .nm{text-align:left}
.nrow{font-size:.9em; padding:.2em 0; border-top:1px solid currentColor; align-items:baseline}
.nrow .nm{font-weight:700}
.nrow.sub .nm{font-weight:400; padding-left:1em}
.nrow.sub2 .nm{font-weight:400; padding-left:2em}
.nrow .v,.nrow .g,.nrow .p{text-align:right; font-variant-numeric:tabular-nums}
.nrow .g{opacity:.68}
.nrow .p{font-weight:700}
.nrow .p.over{color:var(--laccent)}
.label-foot{font-size:.66em; line-height:1.4; opacity:.72; margin:.45em 0 0}
.label-ingredients{font-size:.62em; line-height:1.42; margin:.5em 0 0; opacity:.92}
.label-ingredients b{font-weight:800; letter-spacing:.01em}
.progress{height:.28em; background:color-mix(in srgb,currentColor 20%,transparent);
  border-radius:99px; overflow:hidden; margin-top:.22em}
.progress i{display:block; height:100%; background:currentColor; border-radius:99px;
  transition:width .3s var(--ease)}

/* ============================================================
   App shell
   ============================================================ */
.app{max-width:540px; margin:0 auto; padding:14px 12px 40px}

/* ---------------- card deck ---------------- */
/* The deck clips the neighbouring cards so they read as slivers rather than
   full cards bleeding off the page. */
.deck{position:relative; overflow:hidden; padding:2px 0}
.deckcard{width:calc(100% - 68px); max-width:82%; margin:0 auto;
  display:flex; flex-direction:column; position:relative; z-index:2}

/* carousel previews — a faded look at the card either side. Main page only;
   profile windows deliberately don't get these. */
.deckpeek{
  position:absolute; top:2px; left:50%; z-index:1;
  width:calc(100% - 68px); max-width:82%;
  opacity:.10; pointer-events:none; user-select:none;
  transition:opacity .22s var(--ease), transform .22s var(--ease);
}
.deckpeek > .label{display:flex; flex-direction:column; overflow:hidden}
.deckpeek .listbody{flex:1; min-height:0; overflow:hidden}
.deckpeek .ph-body{flex:1; min-height:0}
/* each sliver dissolves as it runs off the page, so it reads as a hint of
   the next card rather than a second card fighting for attention */
.deckpeek.left{
  transform:translateX(-50%) translateX(-101%) scale(.9);
  -webkit-mask-image:linear-gradient(to left, #000 0, transparent 78%);
          mask-image:linear-gradient(to left, #000 0, transparent 78%);
}
.deckpeek.right{
  transform:translateX(-50%) translateX(101%) scale(.9);
  -webkit-mask-image:linear-gradient(to right, #000 0, transparent 78%);
          mask-image:linear-gradient(to right, #000 0, transparent 78%);
}
.deck:hover .deckpeek.left {transform:translateX(-50%) translateX(-98%) scale(.91); opacity:.18}
.deck:hover .deckpeek.right{transform:translateX(-50%) translateX( 98%) scale(.91); opacity:.18}
/* height is locked in JS to the bBoard card's natural size, then applied
   to every other card so switching cards never resizes the deck */
.deckcard .label{display:flex; flex-direction:column}
.deckcard[style*="height"] .label{height:100%; overflow:hidden}
.deckcard .listcard .listbody{flex:1; min-height:0; overflow-y:auto}
.deckcard .label.placeholder .ph-body{flex:1; min-height:0}
.deckarrow{
  position:absolute; top:50%; transform:translateY(-50%); z-index:3;
  width:28px; height:52px; display:grid; place-items:center; padding:0;
  border:0; background:none; cursor:pointer; color:var(--chrome);
  opacity:.55; transition:opacity .15s var(--ease), color .15s, transform .15s var(--ease);
}
.deckarrow:hover{opacity:1; color:var(--brand)}
.deckarrow:active{transform:translateY(-50%) scale(.9)}
.deckarrow svg{width:22px; height:22px}
.deckarrow.left{left:0}
.deckarrow.right{right:0}

.deckdots{display:flex; gap:6px; justify-content:center; margin-top:12px}
.deckdots button{width:7px; height:7px; padding:0; border-radius:999px; cursor:pointer;
  border:0; background:var(--chrome); opacity:.45;
  transition:background .15s, opacity .15s, transform .15s var(--ease)}
.deckdots button:hover{transform:scale(1.3)}
.deckdots button.on{background:var(--brand); opacity:1; transform:scale(1.15)}

/* placeholder cards for the not-yet-built decks */
.label.placeholder .ph-body{display:grid; place-items:center; gap:7px;
  padding:30px 14px 34px; text-align:center}
.ph-msg{margin:0; font-size:.9em; font-weight:600; opacity:.8}
.ph-soon{margin:0; font-size:.7em; letter-spacing:.14em; text-transform:uppercase; opacity:.42}

.topbar{
  display:flex; align-items:center; gap:6px; margin-bottom:14px;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
  padding:8px 10px; box-shadow:var(--sh-1);
}
.avbtn{
  position:relative; padding:0; border:0; background:none; cursor:pointer;
  border-radius:999px; flex:0 0 auto; line-height:0;
}
.avbtn img{width:36px; height:36px; border-radius:999px; object-fit:cover;
  border:2px solid var(--chrome); transition:border-color .15s, transform .15s var(--ease)}
.avbtn:hover img{border-color:var(--brand); transform:scale(1.05)}
.avbtn .offdot{position:absolute; right:-1px; bottom:-1px; width:11px; height:11px;
  border-radius:999px; background:var(--danger); border:2px solid var(--surface); display:none}
.avbtn.is-off .offdot{display:block}

.toolrow{display:flex; align-items:center; gap:4px; flex:1; justify-content:flex-end}
.tool{
  width:38px; height:38px; display:grid; place-items:center; cursor:pointer; padding:0;
  border:1px solid transparent; border-radius:var(--r-md); background:transparent;
  color:var(--chrome); position:relative;
  transition:background .13s, color .13s, border-color .13s, transform .13s var(--ease);
}
.tool:hover{background:var(--surface-2); border-color:var(--line); color:var(--brand); transform:translateY(-1px)}
.tool:active{transform:translateY(0)}
.tool svg{width:19px; height:19px; display:block}
.tool .dot{position:absolute; top:5px; right:5px; width:8px; height:8px; border-radius:999px;
  background:var(--danger); border:2px solid var(--surface)}

.card{background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
  box-shadow:var(--sh-2); padding:12px; overflow:hidden}

.datebar{display:flex; align-items:center; justify-content:center; gap:6px; margin-top:12px}
.datebar .d{font-weight:700; font-size:14px; min-width:8.5em; text-align:center}

/* ============================================================
   Modals — centered on desktop, bottom sheet on phones
   ============================================================ */
.modal-backdrop{
  /* No backdrop-filter here. Blurring the whole page behind the dialog forces
     the browser to re-rasterise everything underneath on every frame — with
     the card deck and its two peek copies below, that was enough to make
     typing and hovering inside modals feel laggy. A flat scrim costs nothing. */
  position:fixed; inset:0; background:rgba(8,14,20,.58);
  display:grid; place-items:center; padding:16px; z-index:60;
  animation:fade .16s var(--ease);
}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes pop{from{opacity:0; transform:translateY(10px) scale(.985)}to{opacity:1; transform:none}}
@keyframes sheet{from{transform:translateY(100%)}to{transform:none}}

.modal{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
  box-shadow:var(--sh-3); width:100%; max-width:520px; max-height:88dvh;
  display:flex; flex-direction:column; overflow:hidden; animation:pop .2s var(--ease);
}
.modal-head{display:flex; align-items:center; gap:10px; padding:15px 18px 13px;
  border-bottom:1px solid var(--line)}
.modal-head h2{margin:0; font-size:16.5px; flex:1; font-weight:700}
.modal-body{padding:18px; overflow:auto; overscroll-behavior:contain}
.modal-foot{padding:13px 18px; border-top:1px solid var(--line); background:var(--surface-2);
  display:flex; gap:9px; justify-content:flex-end; flex-wrap:wrap}
.x{background:none; border:1px solid transparent; border-radius:var(--r-sm); cursor:pointer;
  color:var(--ink-3); width:30px; height:30px; display:grid; place-items:center; padding:0;
  font-size:19px; line-height:1}
.x:hover{color:var(--ink); background:var(--surface-2); border-color:var(--line)}

.sectitle{font-size:11px; font-weight:750; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 10px}
.sectitle + *{margin-top:0}
.section + .section{margin-top:22px; padding-top:20px; border-top:1px solid var(--line)}

@media (max-width:560px){
  .modal-backdrop{padding:0; place-items:end center}
  .modal{max-width:none; border-radius:20px 20px 0 0; max-height:92dvh;
    animation:sheet .24s var(--ease); border-bottom:0}
  .modal-head{padding-top:18px}
  .modal-head::before{content:''; position:absolute; top:7px; left:50%; transform:translateX(-50%);
    width:38px; height:4px; border-radius:99px; background:var(--line-strong)}
  .modal-head{position:relative}
}

/* ---------------- segmented tabs ---------------- */
.tabs{display:flex; gap:3px; background:var(--sunken); padding:3px;
  border-radius:var(--r-md); margin-bottom:13px; border:1px solid var(--line)}
.tab{flex:1; padding:8px 10px; border:0; background:transparent; border-radius:var(--r-sm);
  cursor:pointer; font-weight:650; font-size:13.5px; color:var(--ink-3);
  transition:background .14s, color .14s, box-shadow .14s}
.tab:hover{color:var(--ink)}
.tab.active{background:var(--surface); color:var(--ink); box-shadow:var(--sh-1)}

.filters{display:flex; gap:8px; margin-bottom:14px; flex-wrap:wrap}
.filters select,.filters input{flex:1 1 120px; min-width:0; padding:8px 10px; font-size:13.5px;
  border:1px solid var(--line-strong); border-radius:var(--r-sm); background:var(--sunken)}
.filters select:focus,.filters input:focus{outline:none; border-color:var(--brand);
  box-shadow:0 0 0 3px var(--brand-soft)}

/* ---------------- rows ---------------- */
.row{display:flex; gap:11px; align-items:center; padding:11px 0; border-top:1px solid var(--line)}
.row:first-child{border-top:0}
.row .rimg{width:36px; height:36px; border-radius:999px; object-fit:cover;
  border:1px solid var(--line); flex:0 0 auto}
.row .body{flex:1; min-width:0}
.row .t{font-weight:650; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.row .s{font-size:12.5px; color:var(--ink-3); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.row .num{font-weight:750; font-variant-numeric:tabular-nums; font-size:15px}

.mealgroup{padding:12px 0 5px; font-size:10.5px; font-weight:750; letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink-3)}
.mealgroup:first-child{padding-top:0}
.empty{padding:34px 16px; text-align:center; color:var(--ink-3); font-size:13.5px}

.ncard{display:flex; gap:11px; padding:12px 0; border-top:1px solid var(--line); align-items:flex-start}
.ncard:first-child{border-top:0}
.ncard.new{background:var(--brand-soft); margin:0 -18px; padding:12px 18px}
.ncard img{width:32px; height:32px; border-radius:999px; object-fit:cover; flex:0 0 auto}
.ncard .nt{font-size:13.5px; line-height:1.45}
.ncard .na{font-size:11.5px; color:var(--ink-3); margin-top:2px}

/* ---------------- floating profile windows ---------------- */
/* overflow stays visible so the side arrows can sit on the edges — the bar
   and inner round their own corners instead */
.floatwin{position:fixed; z-index:50; width:min(340px,92vw); border-radius:var(--r-lg);
  background:var(--surface); box-shadow:var(--sh-3); border:1px solid var(--line);
  animation:pop .18s var(--ease)}
.floatwin .bar{display:flex; align-items:center; gap:9px; padding:9px 10px;
  background:var(--surface-2); border-bottom:1px solid var(--line);
  border-radius:calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
  cursor:grab; touch-action:none; user-select:none}
.floatwin .bar:active{cursor:grabbing}
.floatwin .bar img{width:24px; height:24px; border-radius:999px; object-fit:cover}
.floatwin .bar .t{flex:1; font-weight:650; font-size:13px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
.floatwin .inner{padding:10px; max-height:66dvh; overflow:auto;
  border-radius:0 0 calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px)}
/* every card in a profile window is locked to one height (set inline in JS)
   so cycling through someone's cards never resizes the window */
.floatwin .inner > .label{display:flex; flex-direction:column; overflow:hidden}
.floatwin .listcard .listbody{flex:1; min-height:0; overflow-y:auto}
.floatwin .label.placeholder .ph-body{flex:1; min-height:0}
.floatwin .winarrow{
  position:absolute; top:50%; transform:translateY(-50%); z-index:2;
  width:26px; height:26px; border-radius:999px; padding:0; cursor:pointer;
  display:grid; place-items:center; color:var(--ink-2);
  background:var(--surface); border:1px solid var(--line-strong); box-shadow:var(--sh-1);
  opacity:.55; transition:opacity .15s, color .15s, border-color .15s;
}
.floatwin:hover .winarrow{opacity:1}
.floatwin .winarrow:hover{color:var(--brand); border-color:var(--brand)}
.floatwin .winarrow svg{width:15px; height:15px}
.floatwin .winarrow.left{left:-13px}
.floatwin .winarrow.right{right:-13px}
.floatwin .wincard{font-size:11px; font-weight:650; color:var(--ink-3); text-align:center;
  padding:5px 0 2px; letter-spacing:.03em}

/* ---------------- privacy checklist: one panel, all four inline -------- */
.checkpanel{background:var(--sunken); border:1px solid var(--line);
  border-radius:var(--r-sm); padding:9px 10px}
.checkgrid{display:flex; flex-wrap:wrap; gap:8px 16px}
.checkgrid label{display:flex; align-items:center; gap:7px; cursor:pointer;
  font-size:12.5px; font-weight:600; min-width:0; white-space:nowrap}
.checkgrid label:hover{color:var(--brand)}
.checkgrid input{width:15px; height:15px; accent-color:var(--brand); flex:0 0 auto; margin:0}
@media (max-width:470px){ .checkgrid{gap:9px 14px; font-size:12px} }

/* ---------------- segmented control (theme picker) ---------------- */
.segmented{display:inline-flex; gap:3px; background:var(--sunken); padding:3px;
  border-radius:var(--r-sm); border:1px solid var(--line)}
.segmented button{flex:1; padding:6px 14px; border:0; background:transparent; cursor:pointer;
  border-radius:7px; font-size:12.5px; font-weight:650; color:var(--ink-3);
  transition:background .14s, color .14s, box-shadow .14s}
.segmented button:hover{color:var(--ink)}
.segmented button.on{background:var(--surface); color:var(--ink); box-shadow:var(--sh-1)}

/* ---------------- settings: one size, whichever tab ---------------- */
.modal.settings{max-width:480px}
.modal.settings .modal-body{height:clamp(290px, 64dvh, 500px); padding:15px 16px}
.settingsrow{display:flex; align-items:center; justify-content:space-between; gap:12px}
.settingsrow .lbl{font-size:12.5px; font-weight:700}
.settingsrow .sub{font-size:11px; font-weight:450; color:var(--ink-3); margin-top:1px}

/* compact building blocks used only inside settings */
.setgroup{padding-top:10px; margin-top:10px; border-top:1px solid var(--line)}
.setgroup:first-child{padding-top:0; margin-top:0; border-top:0}
.modal.settings .field{gap:4px; font-size:11.5px}
.modal.settings .field > input,
.modal.settings .field > select,
.modal.settings .field > textarea{padding:8px 10px; font-size:13.5px; border-radius:9px}
.modal.settings .field textarea{min-height:44px; line-height:1.45}
.avrow{display:flex; gap:12px; align-items:center}
.avrow img{width:50px; height:50px; border-radius:999px; object-fit:cover;
  border:2px solid var(--line-strong); flex:0 0 auto}
.filebtn.sm{padding:6px 11px; font-size:12.5px}

/* ---------------- list cards (To-Do / Shopping) ---------------- */
.listcard .listbody{display:flex; flex-direction:column; gap:0}
.listrow{display:flex; align-items:flex-start; gap:.55em; padding:.42em 0;
  border-top:1px solid currentColor; font-size:.86em}
.listrow:first-child{border-top:0}
.listrow input[type=checkbox]{width:1em; height:1em; margin:.18em 0 0; flex:0 0 auto;
  accent-color:currentColor; cursor:pointer}
.listrow .li{flex:1; min-width:0}
/* Everything on a list card paints at full strength in the card's own text
   colour. Faded text was unreadable against a strongly-coloured card — a
   done item is marked by its strike-through and ticked box, not by dimming. */
.listrow .ln{font-weight:700; overflow-wrap:anywhere}
.listrow .lm{font-size:.82em; overflow-wrap:anywhere; margin-top:.1em}
.listrow.done .ln{text-decoration:line-through}
.listrow .lp{font-weight:700; font-variant-numeric:tabular-nums; white-space:nowrap}
.listrow .ledit{border:0; background:none; cursor:pointer; color:inherit; opacity:.75;
  padding:0 .15em; font-size:.95em; line-height:1}
.listrow .ledit:hover{opacity:1}
.listgroup{font-size:.68em; font-weight:800; letter-spacing:.1em; text-transform:uppercase;
  padding:.6em 0 .18em}
.listgroup:first-child{padding-top:0}
.listempty{text-align:center; font-size:.85em; padding:1.6em .5em}
.listfoot{display:flex; justify-content:space-between; font-size:.76em; font-weight:700;
  padding-top:.5em; margin-top:.15em; border-top:1px solid currentColor}
.cardadd{width:1.75em; height:1.75em; display:grid; place-items:center; cursor:pointer;
  border:1px solid currentColor; border-radius:.4em; background:transparent; color:inherit;
  opacity:.8; padding:0; font-size:1em}
.cardadd:hover{opacity:1; background:rgba(127,127,127,.15)}
.cardadd svg{width:1em; height:1em; display:block}

/* ---------------- calendar ---------------- */
.calbox{width:272px; max-width:100%}
.calhead{display:flex; align-items:center; justify-content:space-between; margin-bottom:8px}
.calhead strong{font-size:13px}
.cal{display:grid; grid-template-columns:repeat(7,1fr); gap:3px}
.cal .dow{font-size:9.5px; font-weight:700; color:var(--ink-3); text-align:center;
  padding:1px 0 3px; letter-spacing:.04em}
.cal button{aspect-ratio:1; border:1px solid var(--line); background:var(--sunken);
  border-radius:7px; cursor:pointer; display:grid; place-items:center; padding:0;
  font-size:11.5px; font-weight:600; color:var(--ink-2); transition:all .12s var(--ease)}
.cal button:hover{border-color:var(--brand); color:var(--ink)}
.cal button{position:relative}
.cal button.has{color:var(--ink); border-color:var(--line-strong); background:var(--surface)}
.cal button.has::after{content:''; width:3.5px; height:3.5px; border-radius:99px;
  background:var(--brand); position:absolute; bottom:3px; left:50%; transform:translateX(-50%)}
.cal button.today{box-shadow:inset 0 0 0 2px var(--brand)}
.cal button.sel{background:var(--brand); color:var(--brand-ink); border-color:transparent}
.cal button.sel::after{background:var(--brand-ink)}
.cal button.blank{visibility:hidden}

/* ============================================================
   Colour picker
   ============================================================ */
.swatchbar{display:flex; align-items:center; gap:7px; flex-wrap:wrap;
  padding:9px 10px; background:var(--surface-2); border:1px solid var(--line);
  border-radius:var(--r-md) var(--r-md) 0 0; border-bottom:0}
.swatch{display:inline-flex; align-items:center; gap:7px; padding:5px 9px 5px 5px;
  border:1px solid var(--line-strong); border-radius:999px; background:var(--surface);
  cursor:pointer; font-size:11.5px; font-weight:650; color:var(--ink-2);
  transition:border-color .13s, transform .13s var(--ease)}
.swatch:hover{border-color:var(--brand); transform:translateY(-1px)}
.swatch i{width:19px; height:19px; border-radius:999px; display:block; flex:0 0 auto;
  border:1px solid rgba(128,128,128,.45); box-shadow:inset 0 0 0 1px rgba(255,255,255,.25)}
.swatchbar select{flex:1 1 100%; padding:7px 10px; font-size:12px; font-weight:650;
  border:1px solid var(--line-strong); border-radius:var(--r-sm); background:var(--surface);
  color:var(--ink-2); cursor:pointer}
.swatchbar + .label{border-radius:0 0 var(--r-md) var(--r-md)}
.stylebox{border-radius:var(--r-md); overflow:hidden; box-shadow:var(--sh-1)}

/* ============================================================
   Edit Colors tab — vertical card rail + per-card preview
   ============================================================ */
.colorpane{display:flex; gap:11px; align-items:flex-start}

.vtabs{display:flex; flex-direction:column; gap:3px; flex:0 0 auto; width:38px;
  background:var(--sunken); padding:3px; border-radius:var(--r-md)}
.vtab{display:grid; place-items:center; padding:8px 0; border:0; cursor:pointer;
  background:transparent; border-radius:var(--r-sm); color:var(--ink-2); line-height:1;
  transition:background .13s, box-shadow .13s}
.vtab .e{font-size:16px; display:block; filter:grayscale(.55); opacity:.75;
  transition:filter .13s, opacity .13s}
.vtab .n{display:none}                       /* the emoji is the label */
.vtab:hover{background:var(--surface-2)}
.vtab.active{background:var(--surface); box-shadow:var(--sh-1)}
.vtab.active .e{filter:none; opacity:1}

.colorside{flex:1; min-width:0}
.colorhead{display:flex; align-items:center; justify-content:space-between;
  gap:8px; margin-bottom:7px}
.colorhead .sub{font-size:11.5px; color:var(--ink-3)}
.colorside .swatchbar{padding:7px 8px; gap:5px}
.colorside .swatchbar{border-radius:var(--r-md) var(--r-md) 0 0}
.colorside .swatch{padding:4px 8px 4px 4px; font-size:11px}
.colorside .swatch i{width:16px; height:16px}
.colorside .swatchbar select{padding:5px 8px; font-size:11.5px}
/* the preview only has to read as a preview — keep the pane compact */
.colorside .label{border-radius:0 0 var(--r-md) var(--r-md); font-size:11.2px}

.applywrap{position:relative; flex:0 0 auto}
.applybtn{display:inline-flex; align-items:center; gap:5px; white-space:nowrap}
.applybtn .caret{font-size:10px; opacity:.7}
.applybtn.done{border-color:var(--ok); color:var(--ok)}
.applymenu{display:none; position:absolute; right:0; top:calc(100% + 4px); z-index:70;
  min-width:158px; padding:4px; background:var(--surface); border-radius:var(--r-md);
  border:1px solid var(--line-strong); box-shadow:var(--sh-3)}
.applywrap.open .applymenu{display:block}
.applymenu button{display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  padding:7px 9px; border:0; background:none; cursor:pointer; border-radius:var(--r-sm);
  font-size:12.5px; font-weight:600; color:var(--ink)}
.applymenu button:hover{background:var(--surface-2)}
.applymenu button.all{border-top:1px solid var(--line); margin-top:3px; padding-top:8px;
  border-radius:0 0 var(--r-sm) var(--r-sm); color:var(--ink-2); font-weight:650}

.pickpop{position:fixed; z-index:90; width:228px; padding:11px;
  background:var(--surface); border:1px solid var(--line-strong); border-radius:var(--r-md);
  box-shadow:var(--sh-3); animation:pop .14s var(--ease)}
.pick-sv{position:relative; height:126px; border-radius:var(--r-sm); cursor:crosshair;
  touch-action:none; border:1px solid var(--line)}
.pick-sv .wht{position:absolute; inset:0; border-radius:inherit;
  background:linear-gradient(to right,#fff,rgba(255,255,255,0))}
.pick-sv .blk{position:absolute; inset:0; border-radius:inherit;
  background:linear-gradient(to top,#000,rgba(0,0,0,0))}
.pick-knob{position:absolute; width:14px; height:14px; border-radius:999px; border:2px solid #fff;
  box-shadow:0 0 0 1px rgba(0,0,0,.5), 0 1px 4px rgba(0,0,0,.4); transform:translate(-50%,-50%);
  pointer-events:none}
.pick-hue{position:relative; height:14px; margin-top:10px; border-radius:999px; cursor:pointer;
  touch-action:none; border:1px solid var(--line);
  background:linear-gradient(to right,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
.pick-hue .pick-knob{top:50%}
.pick-foot{display:flex; gap:7px; margin-top:10px; align-items:center}
.pick-foot input{flex:1; min-width:0; padding:7px 9px; font-size:12.5px; font-weight:600;
  font-family:ui-monospace,SFMono-Regular,Consolas,monospace; text-transform:lowercase;
  border:1px solid var(--line-strong); border-radius:var(--r-sm); background:var(--sunken)}
.pick-foot input:focus{outline:none; border-color:var(--brand)}
.pick-eye{width:32px; height:32px; flex:0 0 auto; display:grid; place-items:center; padding:0;
  border:1px solid var(--line-strong); border-radius:var(--r-sm); background:var(--surface);
  cursor:pointer; color:var(--ink-2)}
.pick-eye:hover{border-color:var(--brand); color:var(--brand)}
.pick-eye svg{width:16px; height:16px}
.pick-presets{display:flex; gap:5px; margin-top:9px; flex-wrap:wrap}
.pick-presets button{width:20px; height:20px; border-radius:999px; cursor:pointer; padding:0;
  border:1px solid rgba(128,128,128,.4)}
.pick-presets button:hover{transform:scale(1.15)}

/* ============================================================
   Wizard
   ============================================================ */
.wizwrap{min-height:100dvh; display:flex; align-items:center; justify-content:center; padding:14px}
.wizcard{background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
  box-shadow:var(--sh-3); width:100%; max-width:470px; max-height:calc(100dvh - 28px);
  display:flex; flex-direction:column; overflow:hidden}
.wizhead{padding:20px 22px 0}
.wizhead h1{margin:0 0 2px; font-size:19px}
.wizbody{padding:16px 22px 4px; overflow:auto; scrollbar-width:none; -ms-overflow-style:none}
.wizbody::-webkit-scrollbar{display:none}
.wizfoot{padding:14px 22px 18px; display:flex; gap:9px; justify-content:space-between}
.steps{display:flex; gap:5px; margin:14px 0 0}
.steps i{flex:1; height:3px; border-radius:99px; background:var(--line); transition:background .2s}
.steps i.on{background:var(--brand)}
.wizstep{display:none} .wizstep.on{display:block; animation:fade .2s var(--ease)}
.wizstep h2{font-size:15.5px; margin:0 0 12px}
.avatarpick{display:flex; align-items:center; gap:14px}
.avatarpick img{width:66px; height:66px; border-radius:999px; object-fit:cover;
  border:2px solid var(--line-strong); flex:0 0 auto}
.filebtn{display:inline-block; padding:8px 13px; border:1px solid var(--line-strong);
  border-radius:var(--r-sm); background:var(--sunken); cursor:pointer; font-size:13px;
  font-weight:600; color:var(--ink-2)}
.filebtn:hover{border-color:var(--brand); color:var(--ink)}
.filebtn input{display:none}
.goalgrid{display:grid; grid-template-columns:1fr 1fr; gap:9px}
.goalgrid .field{font-size:11.5px}
.goalgrid .field > input{padding:8px 10px; font-size:13.5px}

@media (max-width:430px){
  .label{font-size:13.6px}
  .label.sm{font-size:11.8px}
  .grid2{grid-template-columns:1fr}
  .app{padding:10px 10px 32px}
  .tool{width:36px; height:36px}
  .toolrow{gap:2px}
  /* narrow phones: give the card every pixel the arrows don't need */
  .deckcard{max-width:100%; width:calc(100% - 56px)}
  .deckpeek{display:none}
  .deckarrow{width:24px}
}

/* ---------------- To-Do: categories, filter chips, edit mode ---------------- */
.listfilter{display:flex; flex-wrap:wrap; gap:5px; padding:0 0 .5em}
.listfilter .chip{padding:.22em .7em; font-size:.72em; font-weight:700; cursor:pointer;
  border:1px solid currentColor; border-radius:999px; background:transparent;
  color:inherit; opacity:.6; transition:opacity .13s, background .13s}
.listfilter .chip:hover{opacity:1}
.listfilter .chip.on{opacity:1; background:rgba(127,127,127,.22)}
/* "No Appointments" — same weight as the list, just centred */
.listnone{font-size:.82em; padding:.5em 0 .2em; opacity:.85}
.listrow .ledit.del{font-size:.85em}
.cardadd.cardedit.on{background:rgba(127,127,127,.25); opacity:1}
.remindrow{margin-top:0; font-size:13px; gap:9px; align-items:flex-start}
.remindrow span{line-height:1.35}
.remindrow.off{opacity:.55}
.field-hint{font-size:11.5px; color:var(--ink-3); margin-top:6px}

/* ---------------- login reminder popup ---------------- */
.alertlist{display:flex; flex-direction:column; gap:8px}
.alertrow{display:flex; gap:10px; align-items:flex-start; padding:10px 11px;
  border:1px solid var(--line); border-radius:var(--r-sm); background:var(--sunken)}
.alertrow .akind{flex:0 0 auto; font-size:10.5px; font-weight:800; letter-spacing:.06em;
  text-transform:uppercase; padding:3px 7px; border-radius:999px; margin-top:1px;
  background:var(--brand-soft); color:var(--brand)}
.alertrow .akind.appointment{background:var(--danger-soft); color:var(--danger)}
.alertrow .an{font-weight:700; font-size:14px; overflow-wrap:anywhere}
.alertrow .aw{font-size:12px; color:var(--ink-2); margin-top:2px; overflow-wrap:anywhere}

/* Appointments pinned to the foot of the To-Do card under the "All" filter */
.apptbox{display:flex; flex-direction:column}
.apptbox.pinbottom{margin-top:auto}
.apptbox .listgroup{padding-top:.6em}

/* card title with its tally beside it: "To-Do List   5 open/1 closed" */
.headwrap{display:flex; align-items:baseline; gap:.65em; flex:1; min-width:0; flex-wrap:wrap}
.headcount{font-size:.62em; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  white-space:pre; opacity:.85}

/* ---------------- top bar identity ---------------- */
.whoami{font-weight:700; font-size:14px; color:var(--chrome); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; max-width:40%}

/* ---------------- workout card ---------------- */
.wodate{display:block; width:100%; margin:.1em 0 0; opacity:.72}
button.wodate{padding:0; border:0; background:none; cursor:pointer; color:inherit;
  font-family:inherit; text-align:left; text-decoration:underline dotted;
  text-underline-offset:.2em}
.wosum{display:grid; grid-template-columns:repeat(3,1fr); gap:.4em; text-align:center;
  padding:.5em 0 .6em; border-bottom:1px solid currentColor}
.wosum b{display:block; font-size:1.5em; font-weight:900; letter-spacing:-.02em;
  font-variant-numeric:tabular-nums; line-height:1.1}
.wosum span{display:block; font-size:.66em; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; opacity:.75}
.listgroup.wogroup{display:flex; justify-content:space-between; align-items:baseline}
.listgroup.wogroup .wok{letter-spacing:.02em}
.listrow.wo{align-items:center}

/* icon pickers (workout kind / cardio type) */
.pickgrid{display:grid; grid-template-columns:repeat(3,1fr); gap:9px}
.picktile{display:flex; flex-direction:column; align-items:center; gap:5px; cursor:pointer;
  padding:15px 8px 12px; border:1px solid var(--line-strong); border-radius:var(--r-md);
  background:var(--sunken); color:var(--ink);
  transition:border-color .13s, transform .13s var(--ease), background .13s}
.picktile:hover{border-color:var(--brand); background:var(--surface); transform:translateY(-2px)}
.picktile img{width:44px; height:44px; object-fit:contain; display:block;
  filter:invert(38%) sepia(12%) saturate(500%) hue-rotate(140deg)}
:root[data-theme="dark"] .picktile img{filter:none}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) .picktile img{filter:none} }
.picktile .pt{font-weight:700; font-size:13px}
.picktile .ps{font-size:10.5px; color:var(--ink-3); text-align:center; line-height:1.25}

.weightbox{display:flex; align-items:center; gap:6px}
.weightbox input{width:84px; padding:7px 9px; text-align:right; font-weight:650;
  font-variant-numeric:tabular-nums; border:1px solid var(--line-strong);
  border-radius:var(--r-sm); background:var(--sunken); color:var(--ink)}
.weightbox input:focus{outline:none; border-color:var(--brand); background:var(--surface);
  box-shadow:0 0 0 2px var(--brand-soft)}
.weightbox span{font-size:12px; font-weight:700; color:var(--ink-3)}

/* card header tools sit in a row, not stacked */
.label-tools{display:flex; align-items:center; gap:5px; flex:0 0 auto}
.label-tools .tool{width:30px; height:30px; border-radius:.4em; color:inherit;
  border:1px solid currentColor; opacity:.8}
.label-tools .tool:hover{opacity:1; background:rgba(127,127,127,.15);
  border-color:currentColor; color:inherit; transform:none}
.label-tools .tool svg{width:15px; height:15px}

/* MET tuning grid, under the weight row */
.metgrid{display:grid; grid-template-columns:repeat(3,1fr); gap:6px}
.metcell{position:relative; display:block; min-width:0}
.metcell b{position:absolute; left:9px; top:50%; transform:translateY(-50%);
  font-size:10.5px; font-weight:500; color:var(--ink-3); pointer-events:none}
.metcell input{padding:8px 9px 8px 62px; border:1px solid var(--line-strong);
  border-radius:8px; background:var(--sunken); width:100%; font-size:13px;
  font-weight:650; font-variant-numeric:tabular-nums; text-align:right; color:var(--ink)}
.metcell input:focus{outline:none; border-color:var(--brand); background:var(--surface);
  box-shadow:0 0 0 2px var(--brand-soft)}

/* avatar dropdown */
.avmenu{position:fixed; z-index:80; min-width:150px; padding:5px;
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--r-md); box-shadow:var(--sh-3); animation:pop .14s var(--ease)}
.avmenu button{display:block; width:100%; text-align:left; padding:9px 11px; border:0;
  background:none; cursor:pointer; border-radius:var(--r-sm); font-size:13.5px;
  font-weight:600; color:var(--ink)}
.avmenu button:hover{background:var(--surface-2)}

/* ---------------- share whitelist ---------------- */
.wlrow{display:flex; gap:7px; align-items:center; margin-bottom:12px}
.wlwho{flex:1; min-width:0; padding:8px 10px; border:1px solid var(--line-strong);
  border-radius:var(--r-sm); background:var(--sunken); color:var(--ink);
  font-size:13.5px; font-weight:600}
.wlwho:focus{outline:none; border-color:var(--brand); background:var(--surface)}
.wllist{display:flex; flex-direction:column; gap:8px}
.wlperson{padding:10px 11px; border:1px solid var(--line); border-radius:var(--r-sm);
  background:var(--sunken)}
.wlname{font-weight:700; font-size:13.5px; display:flex; align-items:center; gap:7px}
.wleveryone{font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
  padding:2px 7px; border-radius:999px; background:var(--brand-soft); color:var(--brand)}
.wlcards{display:flex; flex-wrap:wrap; gap:5px; margin-top:7px}
.wlchip{display:inline-flex; align-items:center; gap:5px; padding:3px 5px 3px 9px;
  border:1px solid var(--line-strong); border-radius:999px; background:var(--surface);
  font-size:11.5px; font-weight:650; color:var(--ink-2)}
.wlchip button{border:0; background:none; cursor:pointer; color:var(--ink-3);
  font-size:14px; line-height:1; padding:0 3px; border-radius:999px}
.wlchip button:hover{color:var(--danger)}

/* "Private" lock pill in the user directory */
.pill.lockpill{display:inline-flex; align-items:center; gap:5px}
.pill.lockpill .lk{font-size:11px; line-height:1}

/* sign out sits at the foot of the avatar menu */
/* Every row in the avatar menu leads with a 20px icon so the labels line up. */
.avmenu button, .avmenu .signout{display:flex; align-items:center; gap:10px}
.avmenu .mi{width:20px; height:20px; flex:0 0 auto; object-fit:contain; display:block}
.avmenu .mi.glyph{display:grid; place-items:center; color:var(--ink-3)}
.avmenu .mi.glyph svg{width:18px; height:18px}
.avmenu .signout{display:flex; padding:9px 11px; border-radius:var(--r-sm);
  font-size:13.5px; font-weight:600; color:var(--danger); text-decoration:none;
  border-top:1px solid var(--line); margin-top:4px; padding-top:10px}
.avmenu .signout:hover{background:var(--danger-soft); text-decoration:none}

/* ---------------- whitelist dialog sizing ---------------- */
/* Only the list scrolls; the dialog itself never gains a scrollbar, and the
   card menu is fixed to the viewport so opening it can't resize anything. */
.modal.wl .modal-body{overflow:hidden; display:flex; flex-direction:column}
.wlbody{display:flex; flex-direction:column; min-height:0; flex:1}
.modal.wl .wllist{flex:1; min-height:0; overflow-y:auto; padding-right:2px}
.wlrow .applymenu{position:fixed; right:auto; max-height:none}

/* ---------------- presence + chat in the user list ---------------- */
.avwrap{position:relative; display:block; flex:0 0 auto; line-height:0}
.presence{position:absolute; right:-1px; bottom:-1px; width:11px; height:11px;
  border-radius:999px; border:2px solid var(--surface); display:block}
.presence.on{background:#22c55e}
.presence.off{background:#9aa4af}
:root[data-theme="dark"] .presence.off{background:#5b6673}
.chatbtn{padding:6px 8px}
.chatbtn svg{width:16px; height:16px; display:block}

/* ---------------- workout sections share the card evenly ---------------- */
.deckcard .wosec,.floatwin .wosec{flex:1 1 0; min-height:0; display:flex; flex-direction:column}
.wosec .listgroup{flex:0 0 auto}

/* ---------------- avatar menu: status ---------------- */
.avhead{font-size:10.5px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-3); padding:7px 11px 4px}
/* One row, "Status: Online", where the value is the control. The option list
   is absolutely positioned so opening it can't resize the menu underneath. */
.statusrow{position:relative; display:flex; align-items:center; gap:6px;
  padding:7px 11px 8px; border-bottom:1px solid var(--line); margin-bottom:4px}
.stlabel{font-size:13px; font-weight:600; color:var(--ink-3); flex:0 0 auto}
.avmenu .stvalue{display:flex; align-items:center; gap:7px; width:auto; flex:1 1 auto;
  padding:4px 7px; border:1px solid transparent; border-radius:var(--r-sm);
  font-size:13px; font-weight:700; color:var(--ink); cursor:pointer}
.avmenu .stvalue:hover{background:var(--surface-2); border-color:var(--line-strong)}
.stcaret{margin-left:auto; font-size:10px; color:var(--ink-3); line-height:1}
.stlist{position:absolute; z-index:2; top:calc(100% - 3px); left:8px; right:8px;
  padding:4px; background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--r-md); box-shadow:var(--sh-3); animation:pop .12s var(--ease)}
.stlist[hidden]{display:none}
.avmenu .stopt{display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  padding:7px 9px; border:0; background:none; cursor:pointer; border-radius:var(--r-sm);
  font-size:13px; font-weight:600; color:var(--ink)}
.avmenu .stopt:hover{background:var(--surface-2)}
.avmenu .stopt.on{background:var(--brand-soft); color:var(--brand)}
.dotm{width:9px; height:9px; border-radius:999px; flex:0 0 auto; display:block}
.dotm.online{background:#22c55e} .dotm.away{background:#f59e0b}
.dotm.invisible{background:#9aa4af}

/* presence dots gain an "away" state */
.presence.online{background:#22c55e}
.presence.away{background:#f59e0b}
.presence.offline{background:#9aa4af}
:root[data-theme="dark"] .presence.offline{background:#5b6673}

/* ---------------- inbox dropdown ---------------- */
.inboxpop{position:fixed; z-index:80; width:308px; padding:5px;
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--r-md); box-shadow:var(--sh-3); animation:pop .14s var(--ease)}
.inboxlist{max-height:min(58dvh, 380px); overflow-y:auto}
.inboxlist .empty{padding:16px 12px; font-size:12.5px; text-align:center; color:var(--ink-3)}
.convo{display:flex; align-items:center; gap:9px; padding:8px 9px; cursor:pointer;
  border-radius:var(--r-sm)}
.convo:hover{background:var(--surface-2)}
.convo .rimg{width:32px; height:32px; border-radius:999px; object-fit:cover; flex:0 0 auto}
.convo .body{flex:1; min-width:0}
.convo .t{font-weight:700; font-size:13px; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap}
.convo .s{font-size:11.5px; color:var(--ink-3); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
.convmeta{display:flex; flex-direction:column; align-items:flex-end; gap:4px; flex:0 0 auto}
.convmeta .when{font-size:10px; color:var(--ink-3); white-space:nowrap}
.unreadbadge{min-width:17px; height:17px; padding:0 5px; border-radius:999px;
  background:var(--danger); color:#fff; font-size:10.5px; font-weight:800;
  display:grid; place-items:center}
.convo.unread .t{font-weight:800}
.convo.unread .s{color:var(--ink-2); font-weight:600}

/* ---------------- chat dock ---------------- */
/* Fixed to the page's bottom-right, laid out row-reverse so the bubble stays
   in the corner and each new conversation appears to its left. align-items
   at the end keeps a minimised panel sitting on the same baseline. */
.chatdock{
  position:fixed; z-index:60; right:16px; bottom:16px;
  display:flex; flex-direction:row-reverse; align-items:flex-end; gap:10px;
  pointer-events:none;
}
.chatdock > *{pointer-events:auto}
.chatbubble{width:54px; height:54px; padding:0; border:0; background:none;
  cursor:pointer; position:relative; flex:0 0 auto;
  transition:transform .12s var(--ease)}
.chatbubble:hover{transform:translateY(-2px)}
.chatbubble img{width:100%; height:100%; object-fit:contain; display:block;
  filter:drop-shadow(0 4px 8px rgba(0,0,0,.35))}

/* ---------------- chat window ---------------- */
.chatwin{position:fixed; z-index:60; width:320px; height:420px; display:flex;
  flex-direction:column; border-radius:var(--r-lg); overflow:hidden;
  background:var(--surface); border:1px solid var(--line); box-shadow:var(--sh-3);
  animation:pop .18s var(--ease)}
/* Docked panels are laid out by the dock, not positioned by hand. */
.chatwin.docked{position:relative; z-index:auto; left:auto; top:auto;
  width:300px; height:400px; flex:0 0 auto}
.chatwin.docked.mini{height:auto}
.chatwin.docked.mini .chatlog,
.chatwin.docked.mini .chatfoot{display:none}
.chatwin.docked.mini{width:190px}
.chatwin .bar{display:flex; align-items:center; gap:9px; padding:8px 10px; flex:0 0 auto;
  background:var(--surface-2); border-bottom:1px solid var(--line);
  cursor:grab; touch-action:none; user-select:none}
.chatwin.docked .bar{cursor:pointer}
.chatwin.docked.mini .bar{border-bottom:0}
.chatwin .bar .mini{background:none; border:0; cursor:pointer; padding:0 4px;
  font-size:17px; line-height:1; color:var(--ink-3); font-weight:700}
.chatwin .bar .mini:hover{color:var(--ink)}
.chatwin .bar .x{padding:0 4px; font-size:17px; line-height:1}
/* When collapsed the two controls shrink so the name keeps the room. */
.chatwin.docked.mini .bar .mini,
.chatwin.docked.mini .bar .x{font-size:14px; padding:0 2px}
.chatwin.docked.mini .bar .t{font-size:12.5px}
.chatwin .bar:active{cursor:grabbing}
.chatwin .bar img{width:24px; height:24px; border-radius:999px; object-fit:cover}
.chatwin .bar .t{flex:1; font-weight:700; font-size:13px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
.chatwin .bar .presence{width:9px; height:9px; right:-2px; bottom:-2px}
.chatlog{flex:1; min-height:0; overflow-y:auto; padding:10px; display:flex;
  flex-direction:column; gap:7px; background:var(--bg)}
.msg{display:flex; flex-direction:column; align-items:flex-start; max-width:82%}
.msg.mine{align-self:flex-end; align-items:flex-end}
.msg .bub{padding:7px 10px; border-radius:13px; font-size:12.5px; line-height:1.4;
  background:var(--surface); border:1px solid var(--line); color:var(--ink);
  overflow-wrap:anywhere; white-space:pre-wrap}
.msg.mine .bub{background:var(--brand); border-color:transparent; color:var(--brand-ink)}
.msg .stamp{font-size:9.5px; color:var(--ink-3); margin-top:2px; padding:0 3px}
.chatfoot{flex:0 0 auto; display:flex; align-items:flex-end; gap:6px; padding:8px;
  border-top:1px solid var(--line); background:var(--surface)}
.chatinput{flex:1; min-width:0; resize:none; max-height:80px; padding:8px 10px;
  border:1px solid var(--line-strong); border-radius:var(--r-sm);
  background:var(--sunken); color:var(--ink); font-size:12.5px; line-height:1.4}
.chatinput:focus{outline:none; border-color:var(--brand); background:var(--surface)}
.emojiwrap{position:relative; flex:0 0 auto}
.emojibtn{width:32px; height:32px; border:1px solid var(--line-strong); background:var(--sunken);
  border-radius:var(--r-sm); cursor:pointer; font-size:15px; line-height:1; padding:0}
.emojibtn:hover{border-color:var(--brand)}
.emojipop{display:none; position:absolute; bottom:calc(100% + 6px); left:0; z-index:5;
  width:212px; padding:6px; background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--r-md); box-shadow:var(--sh-3);
  grid-template-columns:repeat(6,1fr); gap:2px}
.emojipop.open{display:grid}
.emojipop button{border:0; background:none; cursor:pointer; font-size:17px; line-height:1;
  padding:5px; border-radius:6px}
.emojipop button:hover{background:var(--surface-2)}

/* two font pickers in the colour bar */
.fontpick{display:flex; align-items:center; gap:6px; flex:1 1 46%; min-width:0}
.fontpick > span{font-size:10px; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; opacity:.7; white-space:nowrap}
.fontpick select{flex:1; min-width:0}
.swatchbar select{flex:1 1 auto}

/* ============================================================
   The cork board
   ------------------------------------------------------------
   Desktop only. Phones keep the swipe deck, so everything here is
   gated behind .boardmode, which JS sets from a min-width query.
   ============================================================ */
.boardwrap{display:none}
body.boardmode .deck,
body.boardmode .deckdots{display:none}

body.boardmode .boardwrap{
  display:block; position:relative; margin:0 auto;
  max-width:1357px; padding:0 4px;
}
body.boardmode .app{max-width:none; padding:14px 16px 30px}

/* In board mode the top bar is gone entirely — the avatar is pinned to the
   cork and the tool buttons are tacked to its top-right corner. The markup
   stays put so the phone deck, which has no board, keeps its header. */
body.boardmode .topbar{display:none}

.board{
  position:relative; width:100%; aspect-ratio:16/10; min-height:598px;
  border-radius:8px;
  /* the wooden frame, plus the shadow the cork casts inside it */
  border:18px solid transparent;
  border-image:url('/images/board/wood.png') 34 round;
  box-shadow:0 18px 44px rgba(0,0,0,.42), 0 2px 6px rgba(0,0,0,.3);
}
/* The cork lives on its own layer so it can be blurred without dragging the
   focused paper down with it — a filter on .board would apply to every
   descendant, including the note you are trying to read.
   .boardsurface is the clipping window; it must NOT be .board itself, because
   a focused note legitimately flies past the frame and would get cut off. */
.boardsurface{
  position:absolute; inset:0; z-index:0; border-radius:4px; overflow:hidden;
}
/* Two stacked cork layers, cross-faded with opacity.
   Both overhang the clip by 30px: a blur samples past its own edge, finds
   nothing there, and fades to transparent — which is what drew a visible
   rectangle just inside the wood frame. Pushing that fade outside the clip
   means every visible pixel is fully-sampled cork.
   Cross-fading opacity rather than transitioning `filter` also keeps the
   animation on the compositor — Firefox will not run a filter transition
   off the main thread, so the old version stuttered there. */
.corklayer{
  position:absolute; inset:-30px;
  background:url('/images/board/cork.png') repeat; background-size:300px 300px;
}
.corklayer.blur{
  filter:blur(5px) saturate(.8);
  opacity:0; transition:opacity .28s var(--ease); will-change:opacity;
}
.boardwrap.focusing .corklayer.blur{opacity:1}
.board::after{
  content:''; position:absolute; inset:0; pointer-events:none; border-radius:4px; z-index:0;
  box-shadow:inset 0 0 34px rgba(60,34,10,.42), inset 0 2px 5px rgba(40,22,6,.4);
  transition:opacity .28s var(--ease);
}
/* Blur the cork and every *other* note; the focused one stays crisp.
   The blur is applied with NO transition — animating a blur radius means
   re-rendering the whole surface every frame. Instead a plain dark veil
   fades in over the top, which is a compositor-only opacity change, and it
   covers the moment the blur snaps on. */
.boardwrap.focusing .paper:not(.focus){filter:blur(4px); pointer-events:none}
.boardveil{
  position:absolute; inset:0; z-index:5; border-radius:4px; pointer-events:none;
  background:rgba(10,6,2,.62); opacity:0;
  transition:opacity .3s var(--ease);
}
.boardwrap.focusing .boardveil{opacity:1}
.boardwrap.focusing .boardhint{opacity:0}

.boardhint{
  position:absolute; left:50%; transform:translateX(-50%); bottom:10px; z-index:2;
  font-size:11px; font-weight:600; letter-spacing:.03em; color:#4a3418;
  background:rgba(255,255,255,.55); padding:3px 12px; border-radius:999px;
  pointer-events:none; transition:opacity .2s;
}

/* ---------------- a sheet of paper ---------------- */
.paper{
  position:absolute; cursor:pointer; z-index:1; width:240px;
  transform:rotate(var(--rot,0deg));
  transform-origin:50% 8%;
  /* Transform only. A drop-shadow filter here had to be re-rasterised every
     frame of the flight, which is what made the animation feel heavy —
     box-shadow on the sheet is composited instead. */
  transition:transform .34s var(--ease);
}
.paper:hover:not(.focus){transform:rotate(var(--rot,0deg)) translateY(-3px) scale(1.014)}
.paper .sheet > *{box-shadow:0 7px 12px rgba(30,16,4,.45)}
.paper:hover .sheet > *{box-shadow:0 11px 18px rgba(30,16,4,.5)}
.paper .sheet{
  position:absolute; top:0; left:0; width:400px;
  transform:scale(var(--pscale,.6)); transform-origin:top left;
  pointer-events:none;                /* the board view is a preview only */
}
.paper.focus .sheet{pointer-events:auto}

/* The two tacks holding it up. Slot 0 (your own notes) is always white;
   every other person you pin keeps one colour across all their notes. */
.paper{--tack-a:#ffffff; --tack-b:#d8dde3; --tack-c:#9aa3ad}
.paper.slot1{--tack-a:#ff8a8a; --tack-b:#e63b3b; --tack-c:#a81d1d}
.paper.slot2{--tack-a:#ffe9a0; --tack-b:#f0b429; --tack-c:#a97a06}
.paper.slot3{--tack-a:#b9f0c4; --tack-b:#34c759; --tack-c:#1a7a37}
.paper.slot4{--tack-a:#9ec9ff; --tack-b:#3b82e6; --tack-c:#1d4ea8}
.tack{
  position:absolute; top:-7px; width:15px; height:15px; border-radius:999px; z-index:3;
  background:radial-gradient(circle at 34% 30%,
    var(--tack-a) 0%, var(--tack-b) 46%, var(--tack-c) 100%);
  box-shadow:0 2px 3px rgba(0,0,0,.45), inset 0 -1px 2px rgba(0,0,0,.35);
}
.tack.l{left:9px}
.tack.r{right:9px}

/* whose card this is, when it isn't yours */
.pinnedby{
  position:absolute; left:0; bottom:-19px; display:flex; align-items:center; gap:5px;
  font-size:10.5px; font-weight:700; color:#3b2a14; white-space:nowrap;
  background:rgba(255,255,255,.72); padding:2px 7px 2px 3px; border-radius:999px;
  box-shadow:0 1px 3px rgba(0,0,0,.3);
}
.pinnedby img{width:14px; height:14px; border-radius:999px; object-fit:cover}

/* ---------------- focused paper ---------------- */
.paper.focus{
  z-index:40; cursor:default;
  transform:translate(var(--fx,0), var(--fy,0)) scale(var(--fk,1.8)) rotate(0deg);
  transform-origin:50% 50%;
  will-change:transform;
}
.paper.focus .sheet > *{box-shadow:0 14px 26px rgba(0,0,0,.5)}
.paper.nomove{transition:none}
.paper.focus .tack{opacity:0; transition:opacity .2s}
.paper.focus .pinnedby{opacity:0}
.paperclose{
  position:absolute; top:-13px; right:-13px; z-index:5;
  width:26px; height:26px; border-radius:999px; cursor:pointer; padding:0;
  border:1px solid var(--line-strong); background:var(--surface); color:var(--ink);
  font-size:17px; line-height:1; box-shadow:var(--sh-2);
  transform:scale(calc(1 / var(--fk,1)));   /* stays a normal size while zoomed */
}
.paperclose:hover{border-color:var(--danger); color:var(--danger)}

/* ---------------- arranging ---------------- */
.boardwrap.arranging{cursor:crosshair}
.boardwrap.arranging .paper:not(.moving){opacity:.55}
.paper.moving{z-index:50; transition:none; pointer-events:none}
.paper.moving .sheet > *{box-shadow:0 18px 26px rgba(0,0,0,.55)}
.paper.moving .tack{opacity:.4}

/* ---------------- right-click menu ---------------- */
.papermenu{
  position:fixed; z-index:90; min-width:150px; padding:5px;
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--r-md); box-shadow:var(--sh-3); animation:pop .12s var(--ease);
}
.papermenu button{
  display:block; width:100%; text-align:left; padding:8px 11px; border:0;
  background:none; cursor:pointer; border-radius:var(--r-sm);
  font-size:13px; font-weight:600; color:var(--ink);
}
.papermenu button:hover{background:var(--surface-2)}

.boardfail{padding:40px; text-align:center; color:#4a3418; font-weight:600}

/* ---------------- the avatar pin ---------------- */
/* Furniture, not a note: it never rotates, and it has no right-click menu.
   z-index sits above the notes (1) but below a focused one (40). */
/* Moved by right-click → Move. Never rotates. The tack is centred on the top
   edge, and that point is what the move clamps to the cork — the photo itself
   may hang over the frame. */
.avpin{
  position:absolute; z-index:8; width:96px; cursor:pointer;
  display:flex; flex-direction:column; align-items:center;
}
.avpin.dragging{opacity:.85; z-index:45}
.avpin img{
  width:88px; height:88px; border-radius:999px; object-fit:cover; display:block;
  border:4px solid #fdfcf6;                       /* a white photo border */
  box-shadow:0 8px 15px rgba(30,16,4,.5);
  -webkit-user-drag:none; user-select:none; pointer-events:none;
}
/* one tack, centred, black */
.avpin .tack.c{
  position:absolute; top:-8px; left:50%; margin-left:-9px; z-index:3;
  width:18px; height:18px;
  --tack-a:#6c7076; --tack-b:#26292e; --tack-c:#0b0d10;
}
/* Bare text under the photo — no plate, no background. The soft light halo
   is the only concession to legibility, since cork is a busy backdrop. */
.avpin .avname{
  position:relative; margin-top:4px; z-index:4; max-width:120px;
  font-size:13px; font-weight:800; color:#2f2109;
  text-shadow:0 1px 0 rgba(255,255,255,.35);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; text-align:center;
  pointer-events:none;
}
.avpin .offdot{
  position:absolute; right:4px; top:6px; width:15px; height:15px; z-index:5;
  border-radius:999px; background:var(--danger); border:2px solid #fdfcf6;
  display:none;
}
.avpin.is-off .offdot{display:block}

/* ---------------- the notification bell ---------------- */
/* Pinned to the cork wherever the user dropped it. Right-click moves it or
   takes it off the board; it never rotates and never recolours. */
.bellhost{position:absolute; z-index:8; width:52px}
.bellhost[hidden]{display:none}
.bellhost.dragging{opacity:.85}
.bellpin{width:52px; height:52px; padding:0; border:0; background:none;
  position:relative; cursor:pointer; display:block;
  transition:transform .12s var(--ease)}
.bellpin:hover{transform:translateY(-2px)}
.bellpin img{width:100%; height:100%; object-fit:contain; display:block;
  -webkit-user-drag:none; filter:drop-shadow(0 4px 7px rgba(30,16,4,.5))}

/* The header row on phones, where there is no cork to pin anything to.
   Scoped to .toolrow: unscoped, this out-specifies .chatbubble and .bellpin
   and shrinks both of them to header size. */
.toolrow .tool.art{position:relative; width:34px; height:34px; padding:0;
  background:none; border:0; cursor:pointer}
.toolrow .tool.art img{width:26px; height:26px; object-fit:contain; display:block; margin:auto}

/* ---------------- notifications dropdown ---------------- */
/* Same shape as the chat inbox, so the bell and the bubble behave alike. */
/* Pin button in the notifications window header — puts the bell back. */
.modal-head .winpin{
  margin-left:auto; margin-right:8px; padding:5px 12px; border-radius:999px;
  border:1px solid var(--line-strong); background:var(--surface);
  font-size:12px; font-weight:800; color:var(--ink); cursor:pointer;
}
.modal-head .winpin:hover:not([disabled]){border-color:var(--brand); color:var(--brand)}
.modal-head .winpin[disabled]{opacity:.5; cursor:default}

.notifpop{
  position:fixed; z-index:80; width:min(360px,94vw); padding:5px;
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--r-md); box-shadow:var(--sh-3); animation:pop .14s var(--ease);
}
.notiflist{max-height:min(420px,60vh); overflow-y:auto; padding:2px}
.notiflist .ncard{margin-bottom:6px}
.notiflist .ncard:last-child{margin-bottom:0}

/* ---------------- connection banner ---------------- */
/* Sits above the cork (z 5) but below a focused note (z 40), so it never
   covers what you are reading. */
.connnotice{
  position:absolute; z-index:6; left:50%; top:50%; transform:translate(-50%,-50%);
  display:flex; flex-direction:column; align-items:center; gap:5px;
  padding:16px 26px; border-radius:var(--r-lg); text-align:center;
  background:var(--surface); border:1px solid var(--line-strong); box-shadow:var(--sh-3);
}
.connnotice strong{font-size:15px; font-weight:800; letter-spacing:.01em}
.connnotice span{font-size:13px; color:var(--ink-2); font-weight:600}
.connnotice.offline strong{color:var(--danger)}
.connnotice.reconnected strong{color:#22c55e}
.connnotice a{color:var(--brand); font-weight:800; text-decoration:underline;
  text-underline-offset:2px; cursor:pointer}
.connnotice a:hover{text-decoration:none}
/* On the phone deck there is no cork to float over, so it becomes a banner. */
.app > .connnotice{position:static; transform:none; margin-bottom:12px; width:100%}

/* Pin button in a profile window's title bar */
.floatwin .winpin{
  flex:0 0 auto; padding:4px 11px; border-radius:999px; cursor:pointer;
  border:1px solid var(--line-strong); background:var(--surface);
  font-size:11.5px; font-weight:700; color:var(--ink-2);
  transition:border-color .13s, color .13s, background .13s;
}
.floatwin .winpin:hover:not(:disabled){border-color:var(--brand); color:var(--brand)}
.floatwin .winpin.on{border-color:var(--ok); color:var(--ok); background:var(--ok-soft)}
.floatwin .winpin:disabled{cursor:default; opacity:.75}
