/* ============================================================
   Perch — APP
   Sheet overlays (confirm dialog + the row/settings sheet lives in
   data.css), toasts, and the motion keyframes those two use.
   Cut from hdw-ui's app.css: kanban, the command palette, the
   notifications/dump panels, the drive picker, the help dialog and
   the right-side drawer — Perch has none of them.
   ============================================================ */

/* 14 — MODALS (the confirm dialog. The row/settings sheet is .ui-sheet, in data.css) */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.7);z-index:600;display:none;align-items:center;justify-content:center;padding:20px;transition:opacity var(--dur) var(--ease);}
[data-theme="light"] .modal-overlay{background:rgba(0,0,0,0.4);}
.modal-overlay.open{display:flex;}
/* the one confirm dialog (Mark paid) sits above everything, including an open sheet */
#hdwDialog{z-index:2100;}
/* while any modal/sheet is open, freeze the page behind it so the background can't scroll (esp. on phones) */
html.modal-open,html.modal-open body{overflow:hidden;}
/* UNIVERSAL MODAL — fixed-height flex column: the MODAL never scrolls, only the BODY does,
   so the header (title + close) and footer (action buttons) are ALWAYS on screen. */
/* min-width:0 is load-bearing on a phone. The overlay is a flexbox, so the sheet is a flex
   item, and a flex item defaults to min-width:auto — it refuses to shrink below its widest
   content. min-width beats max-width in CSS, so one unbreakable link inside made the sheet
   wider than the screen despite max-width:100%, and the whole sheet slid sideways. */
.modal{background:var(--bg2);border:1px solid var(--border);width:100%;min-width:0;max-width:520px;max-height:calc(92vh / var(--zoom,1));overflow:hidden;display:flex;flex-direction:column;border-radius:var(--r-box);}
.modal-lg{max-width:720px;}
.modal-overlay.open .modal{animation:hdwModalIn .42s var(--spring);}
.modal-header{flex:0 0 auto;padding:18px 22px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;gap:10px;background:transparent;}
.modal-title{font-size:var(--fs-body);font-weight:400;color:var(--fg);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.modal-close{flex:0 0 auto;background:none;border:none;color:var(--fg2);font-size:var(--fs-title);cursor:pointer;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background var(--dur) var(--ease),color var(--dur) var(--ease);}
.modal-close:hover{color:var(--fg);background:var(--bg3);}
.modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:22px;}
.modal-footer{flex:0 0 auto;padding:14px 22px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:8px;background:transparent;flex-wrap:wrap;align-items:center;}
.modal-footer .btn{flex:0 1 auto;}
/* the phone version of this — the confirm dialog becomes a bottom sheet too — is in
   responsive.css, which is where every @media in this kit lives */

/* 17 — FEEDBACK (toast, empty state) */
#toastWrap{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:900;display:flex;flex-direction:column;gap:8px;align-items:center;}
.toast{display:flex;align-items:center;gap:var(--s-3);background:var(--glass-thick);backdrop-filter:var(--glass-fx);-webkit-backdrop-filter:var(--glass-fx);border:1px solid var(--hairline);color:var(--fg);font-size:var(--fs-small);line-height:1.3;padding:10px 14px;box-shadow:var(--shadow-pop);animation:toastIn .18s var(--ease-out);max-width:calc(100vw - 32px);border-radius:var(--r-pill);}
.toast.ok{border-color:var(--c-green);}
.toast.err{border-color:var(--c-red);}
/* the one action a toast ever carries: put it back, for eight seconds */
.toast-undo{flex:0 0 auto;background:none;border:none;padding:0;color:var(--orange);font-family:inherit;font-size:inherit;cursor:pointer;}
.toast-undo:hover{opacity:.8;}
.empty{padding:var(--s-6) var(--s-4);text-align:center;border:1px solid var(--border);border-radius:var(--r-box);}
.empty-title{font-size:var(--fs-heading);font-weight:400;margin-bottom:3px;}
.empty-sub{font-size:var(--fs-small);color:var(--fg2);line-height:1.6;}

/* 17.5 — LIQUID GLASS
   The backdrop behind a sheet blurs and dims the page — that part stays.
   The sheet itself does not: a translucent modal over a scrolling page put
   the page's own text as ghost text under the form fields, in both themes.
   Every sheet is the kit's solid surface (--bg2, already set where .modal is
   defined), fully opaque, with just a hairline border and a shadow to lift
   it off the page. */
.modal{border-color:var(--hairline);box-shadow:var(--shadow-pop);}
/* backdrops behind sheets blur the whole page, not just dim it */
.modal-overlay{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);background:rgba(0,0,0,.45);}
[data-theme="light"] .modal-overlay{background:rgba(0,0,0,.25);}

/* every interactive element: hover, active, disabled — no exceptions */
button:disabled,.btn:disabled,input:disabled{opacity:.4;cursor:not-allowed;}
.btn:disabled:active{transform:none;}

/* 19 — MOTION (@keyframes + reduced-motion) */
@keyframes toastIn{from{opacity:0;transform:translateY(14px) scale(.97);}to{opacity:1;transform:translateY(0) scale(1);}}
@keyframes hdwModalIn{from{opacity:0;transform:translateY(12px) scale(.96);}to{opacity:1;transform:none;}}
@keyframes hdwSheetIn{from{transform:translateY(100%);}to{transform:none;}}
@keyframes hdwDrawerIn{from{transform:translateX(100%);}to{transform:none;}}
@keyframes hdwFadeIn{from{opacity:0;transform:translateY(4px);}to{opacity:1;transform:none;}}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;}
}
