/* ============================================================
   DRILLBAG app stylesheet.
   Rule zero: this is COPIED, not re-derived. Tokens and component rules come from
   pickleball/brand/drillbag-specimen.html (brand canon v1.3) by way of the SEALED mock
   pickleball/specs/mocks/drill-coordinator.html (v1.3.4). Do not invent colors or type here.
   Everything below the "app additions" rule is new surface written in the same voice:
   same tokens, same three-voice law (pink commits, cyan answers, canary is earned).
   ============================================================ */
/* Brand v1.3, the legibility lift (ratified 2026-08-29): copied verbatim from the v1.3
   specimen's :root. Ground deeper, surface-2 tighter, ink/muted/faint lifted, the three
   dims re-derived. Accents, line, surface and type are untouched. Contrast validated in
   the brand doc; do not adjust these by eye. */
:root{
    --ground:#090906; --surface:#14120b; --surface-2:#222018;
    --line:#3c351b;
    --ink:#faf7eb; --ink-strong:#fdfbf5; --muted:#d4d0c4; --faint:#838078;
    --accent:#ff3d8d; --accent-dim:#c2306b;
    --accent2:#41e8f0; --accent2-dim:#33b0b6;
    --accent3:#ffd23d; --accent3-dim:#c2a02f;
    --disp:'Archivo Black','Arial Black',sans-serif;
    --body:'Geist',-apple-system,'Helvetica Neue',sans-serif;
    --mono:'Geist Mono',ui-monospace,Menlo,monospace;
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html,body{background:var(--ground)}
  body{font-family:var(--body);color:var(--ink);-webkit-font-smoothing:antialiased;
       display:flex;justify-content:center;padding:18px 0 60px}
  .phone{width:100%;max-width:390px;background:var(--ground);min-height:100vh;
         border-left:1px solid var(--line);border-right:1px solid var(--line)}

  /* appbar + tabs */
  .appbar{display:flex;align-items:center;justify-content:space-between;
          padding:16px 16px 10px}
  .brandlock{display:flex;align-items:center;gap:9px}
  .brandlock svg{display:block;--mk-face:var(--accent3);--mk-mouth:var(--accent3);--mk-tear:var(--accent2)}
  .wordmark{font-family:var(--disp);font-weight:400;font-size:30px;line-height:1}
  .wordmark .t1{color:var(--accent)}
  .wordmark .t2{color:var(--accent2)}
  .mocktag{font-family:var(--mono);font-size:10px;color:var(--faint);letter-spacing:.12em;font-weight:400}
  .tabs{position:sticky;top:0;z-index:9;display:flex;background:var(--ground);
        border-bottom:1px solid var(--line);padding:0 10px}
  /* Tabs left Geist Mono for Geist 500 (Paul, dry-run): the uppercase and the letterspacing
     stay, the typewriter does not. Mono narrows toward numbers and small labels, brand v1.2.1.
     text-align was the WEEK-against-the-edge bug: these are block anchors, not the mock's
     centred buttons, so they inherited left alignment. */
  .tab{flex:1;background:none;border:none;color:var(--faint);font-family:var(--body);
       font-weight:500;font-size:12px;letter-spacing:.11em;padding:13px 0 11px;
       text-align:center;text-transform:uppercase;
       border-bottom:2px solid transparent;cursor:pointer}
  .tab.on{color:var(--ink);border-bottom-color:var(--accent)}
  .pane{display:none;padding:16px 16px 40px}
  .pane.on{display:block}

  /* shared bits */
  .cap{font-family:var(--mono);font-size:11px;letter-spacing:.14em;color:var(--faint);
       text-transform:uppercase;margin:8px 0 12px;font-weight:500}
  .card{background:var(--surface);border:1px solid var(--line);border-radius:12px;
        padding:16px;margin-bottom:14px}
  .btn{display:block;width:100%;border:none;border-radius:10px;padding:14px;
       font-family:var(--disp);font-weight:400;font-size:16px;letter-spacing:.04em;
       cursor:pointer;text-align:center}
  .btn.prime{background:var(--accent);color:var(--ground)}
  .btn.second{background:var(--accent2);color:var(--ground)}
  .btn.ghost{background:none;border:1px solid var(--line);color:var(--muted);
             font-family:var(--body);font-weight:500;font-size:15px;margin-top:10px}
  .btn.mini{width:auto;display:inline-block;padding:9px 14px;font-size:13.5px}
  .btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .hair{border:none;border-top:1px solid var(--line);margin:14px 0}
  .note{font-size:13px;color:var(--faint);line-height:1.5}
  /* Specimen chip vocabulary, nudged up from 10.5px because Paul could not read them in a
     card at arm's length (dry-run). Same font, same tracking, same pill. */
  .chip{display:inline-block;font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
        font-weight:500;padding:5px 11px;border-radius:99px;border:1px solid var(--line);color:var(--muted)}
  .chip.live{border-color:var(--accent2);color:var(--accent2);
             text-shadow:0 0 14px color-mix(in srgb,var(--accent2) 45%,transparent)}
  .chip.okc{border-color:var(--accent2-dim);color:var(--accent2)}
  /* Waiting states wear canary; a claimable spot is an invitation, and invitations are pink.
     ON and LOCKED keep cyan. (Paul's calls, brand v1.2.1.) */
  .chip.pend{border-color:var(--accent3-dim);color:var(--accent3)}
  .chip.openc{border-color:var(--accent-dim);color:var(--accent)}

  /* invite: session header */
  .host{display:flex;align-items:center;gap:10px;margin-bottom:12px}
  .ava{width:38px;height:38px;border-radius:50%;background:var(--surface-2);
       border:1px solid var(--line);display:flex;align-items:center;justify-content:center;
       font-family:var(--mono);font-weight:500;font-size:13px;color:var(--muted)}
  .host .who{font-size:15px}
  .host .who b{font-weight:500;color:var(--ink-strong)}
  .host .sub{font-size:12px;color:var(--faint)}
  .when{font-family:var(--disp);font-weight:400;font-size:26px;line-height:1.12;
        text-transform:lowercase;color:var(--ink-strong);margin-bottom:2px}
  .when small{display:block;font-size:15px;font-weight:400;color:var(--muted);
              margin-top:3px}
  .where{font-size:14px;color:var(--muted);margin:8px 0 14px}
  .where b{color:var(--ink);font-weight:500}

  /* spots meter */
  .meter{display:flex;align-items:center;gap:8px;margin-bottom:6px}
  .pip{width:14px;height:14px;border-radius:50%;border:1.5px solid var(--faint)}
  .pip.full{background:var(--accent2);border-color:var(--accent2)}
  .pip.opt{border-style:dashed}
  .meter .lbl{font-family:var(--mono);font-size:12px;color:var(--muted);margin-left:4px}
  .stakes{font-size:13px;color:var(--faint);margin-bottom:14px}

  /* roster */
  .roster .row{display:flex;align-items:center;gap:10px;padding:9px 0;
               border-top:1px solid var(--line)}
  .roster .row:first-child{border-top:none}
  .roster .name{font-size:15px}
  .roster .tagr{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--faint)}
  .roster .row.me .name{color:var(--accent2)}
  .roster .row.me .ava{border-color:var(--accent2);color:var(--accent2)}

  /* ON banner — the earned moment wears cyan (Paul's ruling, 2026-08-27) */
  .onbanner{background:var(--accent2);color:var(--ground);border-radius:12px;
            padding:16px;margin-bottom:14px;text-align:center;
            box-shadow:0 0 26px color-mix(in srgb,var(--accent2) 30%,transparent)}
  .onbanner h2{font-family:var(--disp);font-weight:400;font-size:23px;
               text-transform:lowercase;letter-spacing:.01em}
  .onbanner p{font-size:14px;font-weight:500;margin-top:3px}
  @media (prefers-reduced-motion: no-preference){
    .reveal{animation:pop .35s ease-out}
    @keyframes pop{from{transform:scale(.96);opacity:0}to{transform:scale(1);opacity:1}}
  }

  /* identity confirm + inputs */
  .idline{font-size:14px;color:var(--muted);margin-bottom:12px}
  .idline b{color:var(--ink-strong);font-weight:500}
  .idline a{color:var(--faint);text-decoration:underline;cursor:pointer}
  .field{width:100%;background:var(--surface-2);border:1px solid var(--line);border-radius:10px;
         color:var(--ink);font-family:var(--body);font-size:16px;padding:12px;margin-bottom:10px}
  .field::placeholder{color:var(--faint)}
  .field:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .linkline{font-size:13px;color:var(--faint);text-align:center;margin-top:10px}
  .linkline u{cursor:pointer}

  /* folds (CSS chevron, never unicode) */
  .fold{cursor:pointer;display:flex;align-items:center;gap:8px;padding:12px 0;
        font-family:var(--mono);font-weight:500;font-size:11.5px;letter-spacing:.12em;
        color:var(--muted);border-top:1px solid var(--line)}
  .chev{width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;
        border-left:7px solid var(--accent3);transition:transform .15s}
  .fold.open .chev{transform:rotate(90deg)}
  .foldbody{display:none;padding:0 0 12px;font-size:13px;color:var(--muted);line-height:1.6}
  .foldbody b{color:var(--ink-strong);font-weight:500}
  .fold.open + .foldbody{display:block}

  /* post form */
  .frow{margin-bottom:14px}
  .flabel{font-family:var(--mono);font-size:11px;letter-spacing:.14em;color:var(--faint);
          text-transform:uppercase;font-weight:500;margin-bottom:7px}
  .flabel.gold{color:var(--accent3)}
  .seg{display:flex;gap:8px}
  .seg button{flex:1;background:var(--surface-2);border:1px solid var(--line);color:var(--muted);
              border-radius:10px;padding:11px 0;font-family:var(--mono);font-weight:500;
              font-size:15px;cursor:pointer}
  .seg button.sel{background:var(--accent2);border-color:var(--accent2);color:var(--ground)}
  .togrow{display:flex;align-items:center;gap:12px}
  .togrow .txt{font-size:14px;color:var(--muted);flex:1;line-height:1.4}
  .togrow .txt b{color:var(--ink-strong);font-weight:500}
  .edit-when{background:none;border:none;border-bottom:1px dashed var(--accent2);
             color:var(--accent2);font-family:var(--body);font-weight:500;font-size:14px;
             padding:8px 3px;margin:-8px -1px;cursor:pointer}
  .tog{width:44px;height:26px;border-radius:99px;background:var(--line);border:none;
       position:relative;cursor:pointer;flex-shrink:0}
  .tog::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;
              border-radius:50%;background:var(--muted);transition:left .15s}
  .tog.on{background:var(--accent2)}
  .tog.on::after{left:21px;background:var(--ground)}

  /* session (poster) */
  .statechips{display:flex;gap:8px;margin-bottom:12px}
  .sms{background:var(--surface-2);border:1px solid var(--line);border-radius:14px 14px 14px 4px;
       padding:12px 14px;font-size:14px;line-height:1.5;color:var(--ink);margin-bottom:10px}
  .smsbtns{display:flex;gap:8px}
  .smsbtns .btn{font-size:13.5px;padding:10px}

  /* week */
  .day{display:flex;gap:12px;padding:12px 0;border-top:1px solid var(--line)}
  .day.first{border-top:none}
  .drail{width:46px;flex-shrink:0;text-align:center;padding-top:4px}
  .drail .dw{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;color:var(--faint);font-weight:500}
  .drail .dn{font-family:var(--disp);font-weight:400;font-size:21px;line-height:1.2;color:var(--ink-strong)}
  .drail .dn.today{color:var(--accent3)}
  .day .items{flex:1;display:flex;flex-direction:column;gap:8px;min-width:0}
  .mini{background:var(--surface);border:1px solid var(--line);border-radius:10px;
        padding:12px 14px}
  .mini .top{display:flex;align-items:center;gap:8px;margin-bottom:4px}
  .mini .who{font-size:15px;font-weight:500;color:var(--ink-strong)}
  .mini .meta{font-size:13px;color:var(--muted);line-height:1.4}
  .mini .sub{font-size:13px;color:var(--faint);margin-top:2px}
  .mini.quiet{border-style:dashed;background:none;padding:12px 14px;
              font-size:13px;color:var(--faint)}
  .claimrow{display:flex;align-items:center;justify-content:space-between;
            gap:10px;margin-top:10px}
  .claimrow .sub{margin-top:0}

  /* people */
  .tierhead{display:flex;align-items:baseline;gap:8px;margin:18px 0 6px}
  .tierhead h3{font-family:var(--disp);font-weight:400;font-size:15px;letter-spacing:.02em;color:var(--ink-strong)}
  .tierhead .tname{font-family:var(--mono);font-size:12px;color:var(--faint)}
  .prow{display:flex;align-items:center;gap:12px;padding:6px 0;min-height:56px;
        border-top:1px solid var(--line)}
    /* The handle is INSET (phone-test ruling A3). It used to hang off the left with a negative
     margin, which put it under the thumb that was trying to scroll the page at the bezel;
     dragging the edge grabbed a row instead of scrolling. The gutter to its left is plain
     page. touch-action:none stays scoped to the handle and never reaches the row. */
  .drag{width:44px;height:44px;flex-shrink:0;display:flex;flex-direction:column;
        justify-content:center;gap:5px;padding:0 10px;margin-left:0;cursor:grab;
        border-radius:10px}
  .prow{padding-left:14px}
  .drag:active{background:var(--surface-2)}
  .drag i{display:block;height:3px;background:var(--line);border-radius:3px}
  .prow .name{font-size:16px}
  .prow .right{margin-left:auto;display:flex;align-items:center;gap:10px}
  .copybtn{background:none;border:1px solid var(--line);color:var(--muted);border-radius:10px;
           padding:11px 16px;font-size:14px;cursor:pointer;
           font-family:var(--body);font-weight:500;min-height:44px}
  .footnote{font-size:12px;color:var(--faint);line-height:1.6;margin-top:16px;
            border-top:1px solid var(--line);padding-top:12px}
  .resetline{text-align:center;margin-top:22px;font-family:var(--mono);font-size:11px;color:var(--faint)}
  .resetline u{cursor:pointer}
  .hide{display:none}

/* ============================================================
   App additions. Same tokens, same voices, no new colors.
   ============================================================ */

a{color:var(--accent);text-decoration:none}
a.plain{color:inherit;display:block}
form{margin:0}
button{font:inherit}
.tab{text-decoration:none;display:block}

/* the appbar identity line: "You're in as Connor" lives here on every screen */
.whoami{display:flex;align-items:center;justify-content:space-between;gap:10px;
        padding:8px 16px 12px;font-size:13px;color:var(--faint)}
.whoami b{color:var(--muted);font-weight:500}
.whoami a{color:var(--faint);text-decoration:underline;text-underline-offset:3px}

/* Toasts (dry-run fix 3). The old flash was a bordered box that read as an editable field and
   stayed forever. This is the chip vocabulary at sentence length: a pill, centred, gone in
   about three seconds. The fade is triggered by app.js adding .out rather than by a bare CSS
   animation, so with JS off the message just stays put instead of animating itself invisible. */
/* Re-ruled at the phone test (A5): pink, bigger, and FLOATING over the page. The old toast
   was quiet, easy to miss, and pushed the whole page down when it appeared. Fixed position
   means no layout shift at all, JS on or off; the safe-area inset keeps it clear of the home
   indicator. Pink because pink is the action colour and a toast reports an action. */
.toastwrap{position:fixed;left:0;right:0;bottom:0;z-index:60;display:flex;justify-content:center;
           padding:0 14px calc(14px + env(safe-area-inset-bottom));pointer-events:none}
.toast{background:var(--accent);border:none;border-radius:99px;
       padding:14px 20px;font-size:15px;line-height:1.35;color:var(--ground);text-align:center;
       font-weight:500;max-width:390px;
       box-shadow:0 8px 30px rgba(0,0,0,.55),0 0 26px color-mix(in srgb,var(--accent) 30%,transparent)}
.toast b{color:var(--ground);font-weight:500}
/* The one non-pink toast: a dead link is a waiting state, not a completed action, and canary
   is the colour of "not yet" (brand v1.2.1). */
.toast.warn{background:var(--accent3);color:var(--ground)}
.toast.warn b{color:var(--ground)}
@media (prefers-reduced-motion: no-preference){
  .toast{animation:toastin .22s ease-out}
  .toast.out{animation:toastout .45s ease-in forwards}
  @keyframes toastin{from{transform:translateY(14px);opacity:0}to{transform:none;opacity:1}}
  @keyframes toastout{to{transform:translateY(14px);opacity:0}}
}
@media (prefers-reduced-motion: reduce){ .toast.out{opacity:0} }

/* a session card that is also a link */
.mini.tap{display:block;color:inherit}
.mini.tap:active{background:var(--surface-2)}

.stack{display:flex;flex-direction:column;gap:10px}
.rowbtns{display:flex;gap:8px}
.rowbtns .btn{margin-top:0}
.center{text-align:center}
.muted{color:var(--muted)}
.faintline{font-size:12.5px;color:var(--faint);line-height:1.6}
.spacer{height:14px}

/* copy-invite field: the poster's own text thread is the delivery channel */
.copyrow{display:flex;gap:8px;align-items:center;margin-top:8px}
.copyrow input{flex:1;min-width:0;background:var(--surface-2);border:1px solid var(--line);
               border-radius:10px;color:var(--muted);font-family:var(--mono);font-size:11.5px;
               padding:11px 12px}

/* tier picker on the people tab, in the segmented voice */
.tierpick{display:flex;gap:6px}
.tierpick button{background:var(--surface-2);border:1px solid var(--line);color:var(--muted);
                 border-radius:8px;min-width:40px;min-height:40px;font-family:var(--mono);
                 font-size:13px;font-weight:500;cursor:pointer}
.tierpick button.sel{background:var(--accent2);border-color:var(--accent2);color:var(--ground)}

/* metrics: the hypothesis sheet, founders only, mono all the way down */
.mtable{width:100%;border-collapse:collapse;background:var(--surface);
        border:1px solid var(--line);border-radius:10px;overflow:hidden;margin-bottom:16px}
.mtable th{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;
           color:var(--faint);text-align:left;padding:11px 12px 7px;border-bottom:1px solid var(--line);font-weight:500}
.mtable td{padding:10px 12px;font-size:14px;border-bottom:1px solid var(--line);vertical-align:top}
.mtable tr:last-child td{border-bottom:none}
.mtable td.n{font-family:var(--mono);font-size:14px;color:var(--accent);text-align:right;
             white-space:nowrap;font-variant-numeric:tabular-nums}
.mtable td.n.dim{color:var(--muted)}

/* the dry-run bench: founder-only, never linked from an invitee surface */
.bench a{display:block;padding:12px 0;border-top:1px solid var(--line);color:var(--ink);font-size:15px}
.bench a:first-child{border-top:none}
.bench .sub{font-size:12.5px;color:var(--faint)}

.err{color:var(--accent);font-size:13.5px;margin-bottom:10px}
label.flabel{display:block}
select.field{appearance:none}

/* Native controls wearing the mock's clothes, so the form works with JS off.
   Segmented controls are radios; the toggle is a checkbox; the fold is <details>. */
.seg input{position:absolute;opacity:0;width:0;height:0}
.seg label{flex:1;background:var(--surface-2);border:1px solid var(--line);color:var(--muted);
           border-radius:10px;padding:11px 0;font-family:var(--mono);font-weight:500;
           font-size:15px;cursor:pointer;text-align:center;min-height:44px;
           display:flex;align-items:center;justify-content:center}
.seg input:checked + label{background:var(--accent2);border-color:var(--accent2);color:var(--ground)}
.seg input:focus-visible + label{outline:2px solid var(--accent);outline-offset:2px}

.tog input{position:absolute;opacity:0;width:0;height:0}
label.tog{display:block;width:44px;height:26px;border-radius:99px;background:var(--line);
          position:relative;cursor:pointer;flex-shrink:0;border:none}
label.tog::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;
                 border-radius:50%;background:var(--muted);transition:left .15s}
label.tog:has(input:checked){background:var(--accent2)}
label.tog:has(input:checked)::after{left:21px;background:var(--ground)}
label.tog:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}

details.fold{border-top:1px solid var(--line)}
details.fold summary{cursor:pointer;display:flex;align-items:center;gap:8px;padding:12px 0;
  font-family:var(--mono);font-weight:500;font-size:11.5px;letter-spacing:.12em;color:var(--muted);
  list-style:none}
details.fold summary::-webkit-details-marker{display:none}
details.fold summary .chev{transition:transform .15s}
details.fold[open] summary .chev{transform:rotate(90deg)}
details.fold .foldbody{display:block;padding:0 0 12px;font-size:13px;color:var(--muted);line-height:1.6}

.linkline a{color:var(--faint);text-decoration:underline;text-underline-offset:3px}
.mini a.plain{color:inherit;display:block}
.mini a.plain:active{opacity:.7}
/* clipboard fallback: the link, revealed and selectable, rather than a silent failure */
.prow{flex-wrap:wrap}
.prow input.revealed{flex-basis:100%;width:100%;margin:0 0 10px;font-family:var(--mono);font-size:11.5px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:8px;color:var(--muted);padding:10px}

/* ============================================================
   Dry-run fixes, 2026-08-28. Same tokens, same voices, no new colors.
   ============================================================ */

/* Chip pickers (fix 5). The native datetime-local popup is gone from the product: a start is
   a day chip plus a time chip, in the same segmented voice as 60/90/120 and the size rows.
   Radios underneath, so the whole form still posts with JS off. */
.chiprow{display:flex;gap:8px;overflow-x:auto;overflow-y:hidden;padding:2px 0 8px;
         -webkit-overflow-scrolling:touch;scrollbar-width:none}
.chiprow::-webkit-scrollbar{display:none}
.chiprow input{position:absolute;opacity:0;width:0;height:0}
.chiprow label{flex:0 0 auto;background:var(--surface-2);border:1px solid var(--line);
               color:var(--muted);border-radius:10px;cursor:pointer;text-align:center;
               display:flex;align-items:center;justify-content:center;min-height:44px}
.chiprow input:checked + label{background:var(--accent2);border-color:var(--accent2);color:var(--ground)}
.chiprow input:focus-visible + label{outline:2px solid var(--accent);outline-offset:2px}

.daychip{flex-direction:column;gap:1px;min-width:52px;padding:7px 6px}
.daychip .cw{font-family:var(--mono);font-size:10px;letter-spacing:.12em;font-weight:500;opacity:.85}
.daychip .cn{font-family:var(--disp);font-weight:400;font-size:18px;line-height:1.1}
.timechip{gap:3px;padding:0 12px;font-family:var(--mono);font-weight:500;font-size:14px}
.timechip .ap{font-size:9.5px;letter-spacing:.1em;opacity:.8}
.wchip{padding:0 14px;font-family:var(--body);font-weight:500;font-size:14px}

/* The resolved start, spelled out. The dry run's complaint was not knowing when a picker was
   done; this line is always the answer, and app.js keeps it current. */
.whensum{font-family:var(--mono);font-size:12px;letter-spacing:.08em;color:var(--accent3);
         font-weight:500;margin-top:2px}

/* The <details> deadline control that shipped here is gone: it was dead on iOS Safari and
   failed closed. Its replacement is under "Phone-test fixes" at the bottom of this file. */

/* "Somewhere else" reveals free text with no JS at all (fix 6). */
.whereother{display:none;margin-top:2px}
.wherechips:has(#where-other:checked) ~ .whereother{display:block}

/* The just-posted card, lit briefly on landing (fix 4). */
.mini.justposted{border-color:var(--accent)}
@media (prefers-reduced-motion: no-preference){
  .mini.justposted{animation:justposted 2.4s ease-out forwards}
  @keyframes justposted{
    0%{border-color:var(--accent);box-shadow:0 0 22px color-mix(in srgb,var(--accent) 32%,transparent)}
    70%{border-color:var(--accent);box-shadow:0 0 18px color-mix(in srgb,var(--accent) 20%,transparent)}
    100%{border-color:var(--line);box-shadow:none}
  }
}

/* Drag to retier (fix 2). The handle was a dead affordance through the whole dry run.
   touch-action:none on the handle only, so the page still scrolls everywhere else: the
   44px handle is inset from the bezel and the gutter to its left is plain page.
   The intent gesture that sat here (polish fix 4: ~8px sideways or a ~150ms hold before a
   drag began) is REVERTED, on Paul's ruling from video of real iOS hardware — the hold timer
   promoted a scroll that started near a handle into a drag, and the accidental retier
   committed. Pointerdown on the handle starts the drag immediately again. An accidental drag
   while scrolling is the accepted trade. */
.tierlist{min-height:44px}
.drag{touch-action:none;cursor:grab}
.drag:active{cursor:grabbing}
.prow.dragging{position:fixed;z-index:40;opacity:.94;
  background:var(--surface);border:1px solid var(--accent2);border-radius:10px;
  padding:6px 12px;box-shadow:0 10px 26px rgba(0,0,0,.55)}
.prow.dragging .drag i{background:var(--accent2)}
.dropslot{border:1px dashed var(--accent2);border-radius:10px;background:var(--surface-2);
  margin:6px 0}
body.dragging{user-select:none;-webkit-user-select:none}

/* ============================================================
   Phone-test fixes, 2026-08-28. Same tokens, same voices, no new colors.
   ============================================================ */

/* A2. The side lines. The .phone wrap carries the desktop column borders, which on a phone
   land one pixel inside each bezel and read as a frame around the app. Gone below the point
   where the wrap stops being a column and starts being the whole screen; desktop unchanged. */
@media (max-width: 460px){
  .phone{border-left:none;border-right:none;max-width:none}
}

/* A1. The deadline control. <details> is what shipped, and on iOS Safari a <summary> that is
   display:flex stops being a summary: the tap does nothing and the control fails CLOSED, which
   is how a whole ruled feature went missing on Paul's phone. This replacement cannot fail
   closed. With no JS the chip rows are simply open and the toggle is inert; app.js collapses
   them on load and the button opens them again. */
.deadline{flex:1;min-width:0}
.deadtoggle{display:flex;align-items:center;gap:8px;background:none;border:none;padding:11px 0;
  min-height:44px;color:var(--accent2);font-family:var(--body);font-weight:500;font-size:15px;
  cursor:pointer;text-align:left}
.deadtoggle .deadsum{border-bottom:1px dashed var(--accent2)}
.deadtoggle[aria-expanded="true"] .chev{transform:rotate(90deg)}
.deadtoggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.deadbody{padding-top:4px}
.deadbody.shut{display:none}

/* The same WebKit trap in the WHY SIZE MATTERS fold: the flex moved onto an inner span, so
   the summary keeps the display the browser needs to toggle it. */
/* .fold was written for a <div> and sets display:flex, which turns the <details> itself into
   a flex container and puts the body BESIDE the summary. The details is a block; the flex
   belongs on the inner row. */
details.fold{display:block}
details.fold summary{display:list-item;list-style:none}
details.fold summary::-webkit-details-marker{display:none}
details.fold summary .sumrow{display:flex;align-items:center;gap:8px}

/* B1. The week card: one signal per fact. The dots take the right-hand side (they were dead
   space) and the name slot says "Yours" exactly once for a session you posted.

   Polish fix 5, the compaction: the state chip comes back UP to the top row between the name
   and the dots, and the foot row is gone unless it carries I'M IN. Ten or fifteen sessions is
   a lot to scroll, and a card with nothing to do was spending a whole row plus 10px of margin
   saying so. Vertical padding and the inter-line margins come in with it; the names line stays,
   one line, ellipsized. Nothing here changes what the card says. */
.mini{padding:10px 12px}
.mini .top{display:flex;align-items:center;gap:7px;margin-bottom:2px}
.mini .who{flex:0 1 auto;min-width:2.5em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mini .top .chips{display:flex;gap:5px;flex-shrink:0}
.dots{display:flex;align-items:center;gap:5px;flex-shrink:0}
.mini .top .dots{margin-left:auto}
.dots .pip{width:10px;height:10px;border-width:1.5px}
/* .mini .with -- the names line -- is gone as of the fourth polish arc: who is in lives on
   the detail page. It was the third line that made some cards taller than others, and a
   taller card made a taller button beside it. Two lines, everywhere. Its rules went with it.
   The foot row went the same way in the second arc, when the claim moved out of the card;
   between them there is no other action or line a week card carries. */

/* B3. The thumb-reachable back control. The tabs stay where they are; this is in addition,
   for the hand actually holding the phone. The chevron is drawn, never a unicode arrow. */
.backfab{position:fixed;right:16px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:50;
  width:54px;height:54px;border-radius:50%;background:var(--surface-2);
  border:1px solid var(--line);box-shadow:0 8px 24px rgba(0,0,0,.5);
  display:flex;align-items:center;justify-content:center}
.backfab .bchev{width:11px;height:11px;border-left:2.5px solid var(--accent2);
  border-bottom:2.5px solid var(--accent2);transform:rotate(45deg);margin-left:4px}
.backfab:active{background:var(--surface)}
.backfab:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Room for it: the page gets a taller tail, and the toast rides above it rather than under. */
.phone:has(.backfab) .pane{padding-bottom:96px}
.phone:has(.backfab) .toastwrap{padding-bottom:calc(84px + env(safe-area-inset-bottom))}

/* C2. The mute: low-key on purpose, never competing with I'M IN. */
.muterow{margin-top:14px}
.mutebtn{display:block;width:100%;background:none;border:none;padding:12px 0;min-height:44px;
  color:var(--faint);font-family:var(--body);font-size:13px;text-align:center;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px}
.mutebtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.mutedline{font-size:13px;color:var(--faint);line-height:1.5;text-align:center;margin-top:14px}

/* C3. The add-back moment. One card, canary eyebrow (an earned moment), pink action. */
.card.addback{border-color:var(--accent3-dim)}

/* The people row keeps to one line. Adding the thumb gutter above pushed the longer names
   (Marcus V., Connor H.) past the width budget, and the chip and the copy button dropped to a
   second line under the name. The name is the part that can afford to be trimmed. */
.prow .name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prow .right{flex-shrink:0}
/* ...and the width budget it has to fit in: the row is handle + name + state + copy, and on a
   375px screen the copy button was eating the name. Same touch targets (44px minimum), less
   padding around them. */
.prow{gap:10px}
.copybtn{padding:11px 12px;font-size:13.5px}

/* ============================================================
   Second polish arc, 2026-08-29. Same tokens, same voices, no new colors.
   ============================================================ */

/* Fix 2. The day is a stack of rows, one per card, so what sits beside a card belongs to
   THAT card: two sessions on one day each get their own I'M IN, aligned with the session it
   claims. The numeral belongs to the day and rides the first row only. The foot row is gone,
   which is what makes every card the compact shape. */
.day{display:block;padding:12px 0}
.drow{display:flex;gap:8px;align-items:stretch}
.drow + .drow{margin-top:8px}
.drow .mini{flex:1;min-width:0;align-self:flex-start}
.drow .drail{display:flex;flex-direction:column;align-items:center}

/* Fix 4. ALL / MINE, in the post form's segmented voice. Links, not radios: nothing to
   submit and nothing to remember, and it still works with JS off. */
.weekfilter{margin-bottom:14px}
.seg .segl{flex:1;background:var(--surface-2);border:1px solid var(--line);color:var(--muted);
  border-radius:10px;padding:11px 0;font-family:var(--mono);font-weight:500;font-size:13px;
  letter-spacing:.12em;text-align:center;min-height:44px;
  display:flex;align-items:center;justify-content:center}
.seg .segl.on{background:var(--accent2);border-color:var(--accent2);color:var(--ground)}
.seg .segl:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* The MINE empty state is a line, not a card: there is nothing there to act on. */
.quietline{padding:20px 0}

/* Fix 5. The directory rows reuse the people row and the tier picker; the only new thing is
   the word in front of the numbers, in the eyebrow voice. */
.tierpick{align-items:center}
.tierpick .picklbl{font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  color:var(--faint);font-weight:500;margin-right:2px}

/* ============================================================
   Third polish arc, 2026-08-29. Same tokens, same voices, no new colors.
   ============================================================ */

/* Fix 1. I'M IN moves out of the gutter and beside its own card: one uniform row. In the
   gutter it had 44px of width to say "I'M IN" in, so the label stacked onto two rows and the
   button sat under the day numeral, re-creating the vertical space the foot row had cost --
   while the card left the right-hand side of the screen empty. The card narrows by exactly
   the button's width and the button matches the card's height, label on one line. The 44px
   tap floor still does not move: the button is wider than that and, at the card's height,
   always taller. These sizes were ratified on device in the fourth re-test and do not move;
   which SIDE of the card the button sits on was re-ruled there -- see fix 1 at the bottom.

   Nothing is reserved on a row with no action: a card with nothing to do spans the full
   width, because an empty column would put the stretching straight back. */
.rclaim{display:flex;align-self:stretch;flex-shrink:0}
.btn.rowbtn{width:auto;flex:1;min-width:66px;min-height:44px;padding:0 9px;border-radius:10px;
  display:flex;align-items:center;justify-content:center;
  font-size:13.5px;line-height:1;white-space:nowrap}
/* Every pixel the row spends left of the card is a pixel the time-and-where line does not
   have, and that line wraps before anything else does. The day gutter is sized to its own
   content now that it holds nothing but the weekday and the numeral. */
.drow .drail{width:38px;flex-shrink:0}

/* Fix 3. WHY SIZE MATTERS: three entries, three blocks. They were <br>-separated lines inside
   one paragraph and read as a single mono blob. Same type, same colors, same copy -- the only
   change is air between them. */
.foldbody .foldrow + .foldrow{margin-top:10px}

/* Fix 4. OUT sits beside the tier numbers in MOVE SOMEONE, in the same picker, and reads as
   the exit rather than a fourth tier: no fill, and the muted border the ghost button wears. */
.tierpick button.outbtn{width:auto;padding:0 12px;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.12em;margin-left:4px}

/* ============================================================
   Fourth polish arc, 2026-08-29. Same tokens, same voices, no new colors.
   ============================================================ */

/* Fix 1. The row reorders: date gutter | I'M IN | card. Nothing here resizes anything -- the
   button's size and feel were ratified on device and do not move -- it is purely which side
   of the card the button sits on, and that is a DOM-order change in views.js (the form is
   emitted before the card). The reason is alignment: with the button on the right the page
   had two card widths, and the fill dots hug each card's right edge, so they landed on two
   different vertical lines down the week. Every card now ends flush at the pane's right edge,
   and because the dots are the card's last top-row item they right-align to one line, top to
   bottom.

   The claim moment is unchanged in every way that shows: the button disappears, the card
   takes the full width -- now growing leftward, into the space the button leaves -- and the
   same pink highlight fires and fades.

   Fix 2 lives with the .mini rules above (the names line is gone, so every card is two lines
   and every button one height); fix 3 is in src/time.js, because the compact time range is
   one shared formatter rather than anything the stylesheet can say. */
