/* MediaByJoe — portal + auth screens. Shares the brand palette. */
:root{
  --bg:#08080a; --bg-2:#0e0e13; --panel:#17171d; --panel-2:#20202a;
  --line:rgba(255,255,255,.14); --line-2:rgba(255,255,255,.24);
  --ink:#f8f8fb; --ink-dim:#c3c3d1; --muted:#9a9cac;
  --accent:#f5ad38; --accent-2:#ff6a3d; --grad:linear-gradient(100deg,#ffb347,#ff6a3d);
  --ok:#37b57e; --warn:#e8ad52; --danger:#e85b5b;
  --r:14px;
}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--ink);
  font-family:'Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.55;-webkit-font-smoothing:antialiased;
  overflow-x:clip} /* safety net: never scroll sideways. "clip" (not hidden) keeps the sticky header working */
a{color:inherit;text-decoration:none}
h1,h2,h3,.portal-brand,.auth-brand{font-family:'Sora','Inter',sans-serif;letter-spacing:-.02em}
.muted{color:var(--muted)}

/* ---- Buttons / inputs (shared) ---- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:.7rem 1.2rem;border-radius:10px;
  font-weight:600;font-size:.92rem;cursor:pointer;border:1px solid transparent;transition:.2s;font-family:inherit}
.btn-primary{background:var(--grad);color:#1a0f00}
.btn-primary:hover{filter:brightness(1.05);transform:translateY(-1px)}
.btn-ghost{background:transparent;border-color:var(--line-2);color:var(--ink-dim)}
.btn-ghost:hover{color:var(--ink);border-color:var(--accent)}
.btn-block{width:100%}
.btn-sm{padding:.45rem .8rem;font-size:.82rem}
.stack{display:flex;flex-direction:column;gap:1rem}
.stack label,.grid-2 label{display:block;font-size:.8rem;color:var(--ink-dim);font-weight:600}
input,select,textarea{width:100%;min-width:0;max-width:100%;margin-top:.35rem;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;
  color:var(--ink);padding:.7rem .8rem;font:inherit;font-size:1rem;transition:.2s} /* 16px+ stops iOS zoom-on-focus */
/* ---- iOS date/time inputs: the cause of the editor overflowing on phones ----
   Mobile Safari sizes these from their own shadow-DOM content and sets
   -webkit-min-logical-width:intrinsic, so they ignore width:100% and stay wider
   than the drawer. width/min-width alone does NOT fix it — the native
   appearance has to come off, which is safe here because every visual
   property (background, border, radius, padding, font) is already ours. The
   native picker still opens on tap; only the default chrome is dropped.
   Do not "tidy" these rules away — the overflow comes straight back. */
input[type=date],input[type=time],input[type=datetime-local],input[type=month]{
  -webkit-appearance:none;appearance:none;
  -webkit-min-logical-width:0;min-width:0;width:100%;max-width:100%;
  /* appearance:none can collapse the control, so pin the height to match
     the other fields (padding .7rem + 1rem line-box). */
  min-height:2.9rem;
}
/* iOS centres the value and gives it its own margins; the picker icon is a
   separate shadow part that adds width unless it's pushed to the end. */
input[type=date]::-webkit-date-and-time-value,
input[type=time]::-webkit-date-and-time-value,
input[type=datetime-local]::-webkit-date-and-time-value{text-align:left;margin:0}
input[type=date]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator,
input[type=datetime-local]::-webkit-calendar-picker-indicator{margin:0 0 0 auto;flex:0 0 auto}
/* Belt and braces: a date field can never widen its grid/flex track. */
.grid-2 > label,.stack > label{min-width:0}
input:focus,select:focus,textarea:focus{outline:0;border-color:var(--accent);box-shadow:0 0 0 3px rgba(240,168,53,.15)}
.grid-2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:.9rem}
.check{display:flex!important;align-items:flex-start;gap:.6rem;font-size:.9rem;color:var(--ink-dim)}
.check input{width:auto;margin:.15rem 0 0}

/* ---- Password show/hide ---- */
.pw-wrap{position:relative;display:block}
.pw-wrap input{padding-right:4.2rem}
.pw-toggle{position:absolute;right:.55rem;top:50%;transform:translateY(-50%);background:var(--panel-2);
  border:1px solid var(--line);border-radius:7px;color:var(--ink-dim);font-size:.78rem;font-weight:600;
  padding:.32rem .6rem;cursor:pointer;font-family:inherit;transition:.2s;margin-top:.17rem}
.pw-toggle:hover{color:var(--ink);border-color:var(--accent)}

/* ---- Flash ---- */
.flash{padding:.8rem 1rem;border-radius:10px;margin-bottom:1rem;font-size:.92rem;border:1px solid}
.flash-ok{background:rgba(46,160,110,.12);border-color:rgba(46,160,110,.4);color:#8fe3bf}
.flash-err{background:rgba(224,74,74,.12);border-color:rgba(224,74,74,.4);color:#f2a3a3}

/* ---- Auth / setup card ---- */
.auth-body{min-height:100svh;display:grid;place-items:center;padding:1.5rem;
  background:radial-gradient(60% 50% at 70% 10%,rgba(255,106,61,.16),transparent 60%),var(--bg)}
.auth-card{width:100%;max-width:400px;background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:2.4rem 2rem;box-shadow:0 30px 80px rgba(0,0,0,.5)}
.auth-brand{display:inline-block;font-weight:800;font-size:1.4rem;margin-bottom:1.5rem}
.auth-brand span{color:var(--accent)}
.auth-card h1{font-size:1.5rem;margin-bottom:.3rem}
.auth-sub{color:var(--muted);font-size:.92rem;margin-bottom:1.5rem}
.auth-back{display:inline-block;margin-top:1.4rem;color:var(--muted);font-size:.88rem}
.auth-back:hover{color:var(--accent)}
.setup-next{margin:0 0 1.4rem 1.1rem;color:var(--ink-dim);font-size:.92rem;display:grid;gap:.5rem}
.setup-next code{background:var(--bg-2);padding:.1rem .4rem;border-radius:5px;color:var(--accent);font-size:.85em}

/* ---- Portal chrome ---- */
.portal-body{background:var(--bg)}
.portal-top{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap;
  padding:.9rem clamp(1rem,3vw,2rem);background:rgba(12,12,16,.9);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
.portal-brand{font-weight:800;font-size:1.2rem}
.portal-brand span{color:var(--accent)}
.portal-nav{display:flex;gap:.4rem;margin-right:auto}
.portal-nav a{padding:.5rem .95rem;border-radius:8px;color:var(--ink-dim);font-size:.92rem;font-weight:500;transition:.2s}
.portal-nav a:hover{color:var(--ink);background:rgba(255,255,255,.05)}
.portal-nav a.active{color:var(--ink);background:var(--panel-2);box-shadow:inset 0 0 0 1px var(--line)}
.portal-main{max-width:1480px;margin:0 auto;padding:clamp(1.4rem,3vw,2.4rem)}
.portal-foot{text-align:center;color:var(--muted);font-size:.82rem;padding:2rem 1rem}

/* ---- Page head ---- */
.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:1.8rem}
.page-head h1{font-size:1.8rem}
.page-head .muted{font-size:.92rem;margin-top:.2rem}
.year-picker label{font-size:.75rem;color:var(--muted)}
.year-picker select{margin-top:.2rem;min-width:110px}

/* ---- KPI grid ---- */
.kpi-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.9rem;margin-bottom:1.6rem}
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:1.1rem 1.15rem;display:flex;flex-direction:column;gap:.5rem}
.kpi-label{font-size:.74rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-weight:600}
/* Missing fallback fonts here (17 Aug 2026 bug): 'Sora' isn't actually
   loaded anywhere in the portal (no @font-face, no Google Fonts <link> in
   _layout.php — every OTHER use of 'Sora' below already falls back to
   Inter/sans-serif and nobody notices). Without a fallback chain, when
   'Sora' doesn't resolve AND there's no generic keyword, iOS Safari's
   final fallback can land on a SERIF font instead of sans — that's what
   made every number on the dashboard look broken on iPhone. Keep this
   fallback chain even if 'Sora' itself never actually loads. */
.kpi-val{font-family:'Sora','Inter',sans-serif;font-size:1.5rem;font-weight:700}
.kpi-warn .kpi-val{color:var(--warn)}
.kpi-accent{background:linear-gradient(135deg,rgba(255,106,61,.16),rgba(240,168,53,.08));border-color:rgba(240,168,53,.35)}
.kpi-accent .kpi-val{color:var(--accent)}
.kpi-wide{grid-column:1 / -1} /* net-profit: full-width accent bar under the stats */
.kpi-sub{font-size:.74rem;font-weight:600;color:var(--danger)}

/* ---- Panels / charts ---- */
.panel-row{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);gap:1.2rem;margin-bottom:1.6rem}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:1.4rem 1.5rem}
.panel h2{font-size:1.1rem;margin-bottom:1.2rem}
.bars{display:flex;align-items:flex-end;gap:.5rem;height:190px}
.bar-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:.5rem;height:100%}
.bar-track{flex:1;width:100%;display:flex;align-items:flex-end;justify-content:center}
.bar{width:60%;min-width:8px;background:var(--grad);border-radius:5px 5px 0 0;transition:height .5s ease}
.bar.neg{background:linear-gradient(#e04a4a,#7a2222)}
.bar-x{font-size:.7rem;color:var(--muted)}
.hbar-list{list-style:none;display:grid;gap:.85rem}
.hbar-head{display:flex;justify-content:space-between;font-size:.88rem;margin-bottom:.35rem}
.hbar-track{height:8px;background:var(--bg-2);border-radius:99px;overflow:hidden}
.hbar{display:block;height:100%;background:var(--grad);border-radius:99px;transition:width .6s ease}

.quick-add{display:flex;gap:.7rem;flex-wrap:wrap}

/* ---- Tables ---- */
.table-wrap{overflow-x:auto;background:var(--panel);border:1px solid var(--line);border-radius:var(--r)}
table.data{width:100%;border-collapse:collapse;min-width:720px}
table.data th{text-align:left;font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);
  font-weight:600;padding:.9rem 1rem;border-bottom:1px solid var(--line)}
table.data td{padding:.85rem 1rem;border-bottom:1px solid var(--line);font-size:.92rem;vertical-align:top}
table.data tr:last-child td{border-bottom:0}
table.data tbody tr:hover{background:rgba(255,255,255,.05)}
.num{text-align:right;font-variant-numeric:tabular-nums}
.owed{color:var(--warn);font-weight:600}
.cell-note{display:block;color:var(--muted);font-size:.8rem;margin-top:.2rem;max-width:38ch}
.empty{text-align:center;color:var(--muted);padding:2.4rem!important}
.tag{background:var(--bg-2);border:1px solid var(--line);border-radius:6px;padding:.2rem .55rem;font-size:.78rem;color:var(--ink-dim)}
.badge{border-radius:6px;padding:.22rem .6rem;font-size:.76rem;font-weight:600;display:inline-block}
.badge.is-paid{background:rgba(55,181,126,.22);color:#8ceac0}
.badge.is-part{background:rgba(245,173,56,.22);color:#ffc55e}
.badge.is-out{background:rgba(232,91,91,.22);color:#ffb1b1}
.badge.is-booked{background:rgba(103,150,245,.22);color:#b7cdff}
.badge.is-enquiry{background:rgba(255,255,255,.12);color:var(--ink)}
.badge.is-sent{background:rgba(103,150,245,.22);color:#b7cdff}
.badge.is-draft{background:rgba(255,255,255,.12);color:var(--ink)}
.row-actions{white-space:nowrap;text-align:right}
.row-actions form{display:inline}
.link{color:var(--accent);font-size:.86rem;font-weight:600;background:none;border:0;cursor:pointer;padding:0 .1rem;font-family:inherit}
.link:hover{text-decoration:underline}
.link-danger{color:#f2a3a3;margin-left:.7rem}

/* ===================================================================
   Card list + action buttons — the shared pattern for every section.
   Mobile-first: cards stack on phones, flow into columns on desktop.
   =================================================================== */
/* min() keeps the 360px track from ever exceeding a narrow phone's width */
.card-list{display:grid;gap:.85rem;grid-template-columns:repeat(auto-fill,minmax(min(360px,100%),1fr))}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  padding:1rem 1.1rem;display:flex;flex-direction:column;gap:.75rem;transition:border-color .15s,transform .15s}
.card:hover{border-color:var(--line-2)}
.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:.7rem}
.card-badges{display:inline-flex;align-items:center;gap:.35rem;flex-wrap:wrap;justify-content:flex-end;flex:0 0 auto}
.card-title{font-family:'Sora',sans-serif;font-weight:700;font-size:1.02rem;line-height:1.22;min-width:0;overflow-wrap:anywhere}
.card-title .sub{display:block;color:var(--muted);font-size:.82rem;font-weight:500;margin-top:.15rem;font-family:'Inter',sans-serif;overflow-wrap:anywhere}
/* The client's legal name, shown under a display_name (17 Aug 2026) —
   deliberately a size step below the normal .sub, e.g. "440 Venue" big,
   "Inhibition Venues Ltd" tiny beneath it. */
.card-title .sub.sub-legal{font-size:.72rem;opacity:.75;margin-top:.05rem}
.card-meta{display:flex;flex-wrap:wrap;gap:.65rem 1.3rem}
.card-meta .m{display:flex;flex-direction:column;gap:.12rem;min-width:0}
.card-meta .m .k{font-size:.64rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:700}
.card-meta .m .v{font-size:.92rem;color:var(--ink);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.card-meta .m .v.owed{color:var(--warn);font-weight:600}
.card-meta .m .v.pos{color:var(--ok)}
.card-note{font-size:.85rem;color:var(--ink-dim);background:var(--bg-2);border:1px solid var(--line);border-radius:9px;padding:.5rem .7rem;white-space:pre-line}
.card-actions{display:flex;gap:.5rem;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:.75rem;margin-top:auto}
.card-actions form{display:inline-flex;margin:0}
.card-empty{grid-column:1/-1;background:var(--panel);border:1px dashed var(--line-2);border-radius:var(--r);
  padding:2.6rem 1.2rem;text-align:center;color:var(--muted)}

/* View switcher: cards vs compact list */
.view-toggle{display:inline-flex;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:2px;gap:2px}
.view-toggle button{display:inline-flex;align-items:center;gap:.35rem;min-height:36px;padding:.35rem .7rem;border:0;
  border-radius:8px;background:transparent;color:var(--muted);font-weight:600;font-size:.8rem;cursor:pointer;font-family:inherit;transition:.15s}
.view-toggle button:hover{color:var(--ink)}
.view-toggle button.on{background:var(--panel-2);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}

/* Compact list mode — identical markup, denser layout */
.card-list.as-list{grid-template-columns:minmax(0,1fr);gap:.4rem}
.card-list.as-list .card{flex-direction:row;flex-wrap:wrap;align-items:center;gap:.5rem .9rem;padding:.6rem .8rem}
.card-list.as-list .card-top{flex:1 1 190px;align-items:center;gap:.5rem;min-width:0}
.card-list.as-list .card-title{font-size:.92rem}
.card-list.as-list .card-title .sub{display:inline;margin:0 0 0 .4rem;font-size:.78rem}
.card-list.as-list .card-title .sub.sub-legal{font-size:.7rem;opacity:.7}
.card-list.as-list .card-meta{flex:3 1 240px;gap:.25rem .9rem;min-width:0}
.card-list.as-list .card-meta .m{flex-direction:row;align-items:baseline;gap:.3rem}
.card-list.as-list .card-meta .m .k{font-size:.6rem}
.card-list.as-list .card-meta .m .v{font-size:.82rem}
.card-list.as-list .card-note{display:none}
/* flex-shrink must stay 1 here: with `0 0 auto` the button row sizes to
   max-content and refuses to wrap, pushing narrow screens sideways. */
.card-list.as-list .card-actions{border-top:0;padding-top:0;margin:0;flex:0 1 auto;min-width:0}
.card-list.as-list .btn-act{min-height:34px;padding:.3rem .6rem;font-size:.78rem}

/* Action buttons — proper tap targets that replace the old tiny text links */
.btn-act{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;min-height:40px;
  padding:.5rem .9rem;border-radius:10px;font-weight:600;font-size:.85rem;cursor:pointer;font-family:inherit;
  border:1px solid var(--line-2);background:var(--panel-2);color:var(--ink-dim);transition:.15s;white-space:nowrap;text-decoration:none}
.btn-act:hover{color:var(--ink);border-color:var(--accent)}
.btn-act.accent{color:var(--accent);border-color:rgba(245,173,56,.45)}
.btn-act.accent:hover{background:rgba(245,173,56,.12);color:var(--accent)}
.btn-act.danger{color:#f2a3a3;border-color:rgba(232,91,91,.35)}
.btn-act.danger:hover{background:rgba(232,91,91,.14);border-color:var(--danger);color:#ffb1b1}
.btn-act .ico{font-size:1rem;line-height:1}

/* Floating "add" button — thumb-friendly on phones */
.fab{display:none}
@media(max-width:700px){
  .fab{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;position:fixed;
    right:1rem;bottom:1rem;z-index:40;min-height:52px;padding:.9rem 1.4rem;border-radius:99px;
    background:var(--grad);color:#1a0f00;font-weight:700;font-size:.95rem;border:0;cursor:pointer;
    box-shadow:0 10px 30px rgba(255,106,61,.35);font-family:inherit}
  .fab .ico{font-size:1.2rem}
}

/* ---- Time-on-site fields ---- */
.time-field{display:flex;gap:.4rem;align-items:stretch;min-width:0}
.time-field input[type=time]{margin-top:0;min-width:0;flex:1 1 auto}
.time-field .btn-now{flex:0 0 auto}
.btn-now{flex:0 0 auto;background:var(--panel-2);border:1px solid var(--line-2);color:var(--ink-dim);
  border-radius:8px;padding:0 .8rem;font-weight:600;font-size:.82rem;cursor:pointer;font-family:inherit;transition:.2s;white-space:nowrap}
.btn-now:hover{color:var(--accent);border-color:var(--accent)}
.time-onsite-hint{font-size:.82rem;color:var(--muted);margin-top:-.4rem}
.time-onsite-hint strong{color:var(--ink-dim)}

/* ---- Calendar ---- */
.cal-nav{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:1rem}
.cal-month{font-family:'Sora',sans-serif;font-weight:700;font-size:1.15rem}
.cal-month .link{font-size:.82rem;font-weight:600}
.cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px;margin-bottom:1.6rem}
.cal-weekday{font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:600;text-align:center;padding:.3rem 0}
.cal-cell{background:var(--panel);border:1px solid var(--line);border-radius:10px;min-height:96px;padding:.4rem;display:flex;flex-direction:column;gap:.3rem}
.cal-cell.blank{background:transparent;border-color:transparent}
.cal-daynum{font-size:.78rem;color:var(--muted);font-weight:600;line-height:1;align-self:flex-start;
  display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;border-radius:50%;transition:.15s}
.cal-daynum:hover{background:var(--panel-2);color:var(--ink)}
.cal-today{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.cal-today .cal-daynum{color:var(--accent)}
.cal-chips{display:flex;flex-direction:column;gap:.25rem;overflow:hidden}
.cal-chip{display:block;font-size:.72rem;line-height:1.25;padding:.2rem .4rem;border-radius:6px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:var(--panel-2);color:var(--ink);border-left:3px solid var(--muted)}
.cal-chip:hover{filter:brightness(1.15)}
.cal-chip.is-paid{border-left-color:#37b57e}
.cal-chip.is-part{border-left-color:#f5ad38}
.cal-chip.is-out{border-left-color:#e85b5b}
.cal-chip.is-booked{border-left-color:#6796f5}
.cal-chip.is-enquiry{border-left-color:var(--ink-dim)}

/* Range switcher: Day / 7 days / 14 days / Month */
.cal-views{display:inline-flex;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:2px;gap:2px;flex-wrap:wrap}
.cal-views a{display:inline-flex;align-items:center;min-height:36px;padding:.35rem .75rem;border-radius:8px;
  color:var(--muted);font-weight:600;font-size:.8rem;transition:.15s;white-space:nowrap}
.cal-views a:hover{color:var(--ink)}
.cal-views a.on{background:var(--panel-2);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}

/* Tap-to-open day count shown on the month grid (phones only) */
.cal-daycount{display:none}

/* Day-by-day agenda — the readable view (day / 7 / 14 days, and month's agenda) */
.cal-days{display:grid;gap:.6rem;grid-template-columns:minmax(0,1fr)}
.cal-day{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.cal-day.is-today{border-color:var(--accent)}
.cal-day-head{display:flex;align-items:baseline;gap:.5rem;padding:.55rem .9rem;background:var(--panel-2);border-bottom:1px solid var(--line)}
.cal-day-num{font-family:'Sora',sans-serif;font-weight:700;font-size:1.05rem}
.cal-day-dow,.cal-day-mon{font-size:.74rem;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;font-weight:700}
.cal-day-count{margin-left:auto;font-size:.75rem;color:var(--muted);white-space:nowrap}
.cal-day.is-today .cal-day-num{color:var(--accent)}
.cal-day-body{display:grid;gap:.4rem;padding:.6rem .7rem;grid-template-columns:minmax(0,1fr)}
.cal-day-empty{color:var(--muted);font-size:.85rem;padding:.15rem .3rem}

.cal-entry{display:flex;align-items:center;gap:.7rem;padding:.6rem .7rem;border-radius:10px;
  background:var(--bg-2);border:1px solid var(--line);transition:.15s;min-width:0}
.cal-entry:hover{border-color:var(--accent)}
.cal-entry-bar{flex:0 0 4px;align-self:stretch;border-radius:3px;background:var(--muted)}
.cal-entry-bar.is-paid{background:#37b57e}
.cal-entry-bar.is-part{background:#f5ad38}
.cal-entry-bar.is-out{background:#e85b5b}
.cal-entry-bar.is-booked{background:#6796f5}
.cal-entry-bar.is-enquiry{background:var(--ink-dim)}
.cal-entry-main{flex:1;min-width:0}
.cal-entry-title{display:block;font-weight:600;font-size:.95rem;overflow-wrap:anywhere}
.cal-day-of{display:inline-block;margin-left:.45rem;background:var(--panel-2);border:1px solid var(--line);
  border-radius:5px;padding:.05rem .35rem;font-size:.66rem;font-weight:700;color:var(--muted);vertical-align:middle}
.cal-entry-sub{display:block;font-size:.8rem;color:var(--muted);overflow-wrap:anywhere}
.cal-entry-sub strong{color:var(--ink-dim);font-weight:600}
.cal-entry .badge{flex:0 0 auto}

/* Agenda list (mobile-friendly, tappable) */
.cal-agenda{margin-bottom:1.4rem}
.agenda-list{list-style:none;display:grid;gap:.2rem;grid-template-columns:minmax(0,1fr)} /* minmax(0,..) lets rows shrink on phones */
.agenda-row{display:flex;align-items:center;gap:.9rem;padding:.7rem .5rem;border-radius:10px;border:1px solid transparent;transition:.15s;min-width:0}
.agenda-row:hover{background:rgba(255,255,255,.05);border-color:var(--line)}
.agenda-date{flex:0 0 2.6rem;text-align:center;line-height:1.1}
.agenda-date strong{display:block;font-family:'Sora',sans-serif;font-size:1.15rem}
.agenda-date .muted{font-size:.68rem;text-transform:uppercase;letter-spacing:.05em}
.agenda-main{flex:1;min-width:0}
.agenda-title{display:block;font-weight:600;font-size:.95rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agenda-meta{display:block;font-size:.8rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ---- Inline "new client" fields ---- */
.new-client-fields{display:grid;gap:.9rem;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:.9rem .9rem .3rem;margin-top:-.3rem}
.new-client-fields[hidden]{display:none}

/* ---- Drawer (slide-in editor on phones, centered modal on desktop) ---- */
.drawer{position:fixed;inset:0;z-index:60;pointer-events:none;opacity:0;transition:opacity .25s}
/* Stacking is correct here (z-index:60, above everything) — the backdrop
   really does sit on top and blocks clicks through to the page. The bug
   this fixes (17 Aug 2026) was that .55 opacity wasn't dark enough to hide
   a BRIGHT element behind it — the orange "Live" filter-count badge showed
   through clearly against the near-black theme and read as "on top of the
   window" even though it wasn't. Darker + blurred so nothing behind stays
   legible, regardless of how saturated its color is. */
.drawer::before{content:"";position:absolute;inset:0;background:rgba(0,0,0,.72);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);opacity:0;transition:.25s}
.drawer.open{pointer-events:auto;opacity:1}
.drawer.open::before{opacity:1}
.drawer-inner{position:absolute;top:0;right:0;height:100%;width:min(440px,92vw);overflow-y:auto;overflow-x:hidden;
  background:var(--panel);border-left:1px solid var(--line);padding:1.6rem 1.5rem;transform:translateX(100%);transition:transform .3s ease}
.drawer.open .drawer-inner{transform:none}
.drawer-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:.4rem}
.drawer-head h2{font-size:1.25rem}
.drawer-x{font-size:1.2rem;color:var(--muted);width:34px;height:34px;display:grid;place-items:center;border-radius:8px}
.drawer-x:hover{background:var(--bg-2);color:var(--ink)}
.drawer-actions{display:flex;gap:.7rem;margin-top:.6rem}

/* Desktop: enough screen real estate that a right-hand sidebar wastes most of
   it. Same markup, same open/close JS — just re-laid-out as a big centered
   modal instead of a slide-in panel. */
@media(min-width:901px){
  .drawer{display:flex;align-items:center;justify-content:center;padding:2.4rem}
  .drawer-inner{position:relative;top:auto;right:auto;height:auto;max-height:100%;
    width:min(760px,90vw);border-left:0;border:1px solid var(--line-2);border-radius:var(--r);
    box-shadow:0 30px 90px rgba(0,0,0,.6);padding:2rem 2.2rem;
    transform:translateY(14px) scale(.97);transition:transform .25s ease}
  .drawer.open .drawer-inner{transform:none}
  .drawer-head h2{font-size:1.4rem}
  /* Fields breathe more in the wider box — two columns stay comfortably readable
     rather than the cramped pairing a 440px sidebar forced them into. */
  .drawer-inner .grid-2{gap:1.1rem}
  .drawer-inner textarea{min-height:5rem}
}

/* ---- Business switcher (only rendered when you can reach more than one) ---- */
.biz-switch{margin:0}
.biz-switch select{margin-top:0;min-width:150px;max-width:200px;padding:.4rem .6rem;font-size:.85rem;
  background:var(--panel-2);border-color:var(--line-2);font-weight:600}
@media(max-width:700px){
  /* Row 1: brand · selector · avatar (nav wraps to row 2 via order:3).
     The avatar must be last so the dropdown's right:0 anchors to the screen
     edge — otherwise the menu hangs off the left of the viewport. */
  .biz-switch{order:1}
  .biz-switch select{min-width:0;max-width:34vw;font-size:16px} /* 16px stops iOS zoom-on-focus */
}

/* ---- Nav badge + account link ---- */
.portal-nav a{position:relative;display:inline-flex;align-items:center;gap:.4rem}
.nav-badge{background:var(--grad);color:#1a0f00;font-size:.68rem;font-weight:700;line-height:1;
  padding:.15rem .4rem;border-radius:99px;min-width:1.1rem;text-align:center}

/* ---- Profile menu (avatar -> Settings / Admin / Sign out) ---- */
.profile{position:relative;flex:0 0 auto}
.profile-btn{position:relative;background:none;border:0;padding:0;cursor:pointer;border-radius:50%;
  line-height:0;transition:.15s}
.profile-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.avatar{display:grid;place-items:center;width:38px;height:38px;border-radius:50%;background:var(--grad);
  color:#1a0f00;font-weight:800;font-size:.82rem;letter-spacing:.02em;font-family:'Sora',sans-serif;
  box-shadow:0 0 0 1px rgba(255,255,255,.14)}
.profile-btn:hover .avatar{filter:brightness(1.08)}
.profile-dot{position:absolute;top:-1px;right:-1px;width:10px;height:10px;border-radius:50%;
  background:var(--danger);box-shadow:0 0 0 2px var(--bg)}
.profile-menu{position:absolute;top:calc(100% + .6rem);right:0;z-index:60;min-width:230px;
  background:var(--panel);border:1px solid var(--line-2);border-radius:12px;padding:.4rem;
  box-shadow:0 18px 50px rgba(0,0,0,.6);display:grid;gap:2px}
.profile-menu[hidden]{display:none}
.profile-head{padding:.6rem .7rem .7rem;border-bottom:1px solid var(--line);margin-bottom:.3rem;display:grid;gap:.15rem}
.profile-head strong{font-size:.92rem;overflow-wrap:anywhere}
.profile-head .muted{font-size:.78rem;overflow-wrap:anywhere}
.profile-head .tag{justify-self:start;margin-top:.3rem;font-size:.7rem}
.profile-menu a{display:flex;align-items:center;gap:.6rem;min-height:40px;padding:.5rem .7rem;border-radius:8px;
  color:var(--ink-dim);font-size:.9rem;font-weight:600;transition:.15s}
.profile-menu a:hover{background:var(--panel-2);color:var(--ink)}
.profile-menu a.on{background:var(--panel-2);color:var(--ink)}
.profile-menu a.danger{color:#f2a3a3}
.profile-menu a.danger:hover{background:rgba(232,91,91,.14);color:#ffb1b1}
.profile-menu .ico{font-size:.95rem;width:1.1rem;text-align:center}

/* ---- Header actions ---- */
.head-actions{display:flex;gap:.6rem;align-items:center;flex-wrap:wrap}

/* ---- Messages inbox ---- */
.msg-list{display:grid;gap:.9rem}
.msg{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:1.2rem 1.3rem}
.msg-unread{border-color:rgba(240,168,53,.4);box-shadow:inset 3px 0 0 var(--accent)}
.msg-head{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:.4rem}
.msg-head strong{font-size:1.05rem;margin-right:.5rem}
.msg-head .badge,.msg-head .tag{margin-left:.4rem}
.msg-date{font-size:.82rem;white-space:nowrap}
.msg-contact{font-size:.88rem;margin-bottom:.7rem}
.msg-contact a{color:var(--accent)}
.msg-body{color:var(--ink-dim);font-size:.95rem;white-space:pre-line;margin-bottom:1rem}
.msg-actions{display:flex;align-items:center;gap:1rem;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:.8rem}
.msg-actions form{display:inline}

/* ---- Attachments ---- */
.att-chips{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.4rem}
.att-chip{display:inline-flex;align-items:center;gap:.3rem;min-width:0;overflow-wrap:anywhere;background:var(--bg-2);border:1px solid var(--line);
  border-radius:6px;padding:.2rem .55rem;font-size:.76rem;color:var(--ink-dim);max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:.2s}
.att-chip:hover{color:var(--accent);border-color:var(--accent)}
.att-list{display:grid;gap:.45rem;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:.7rem .8rem;
  grid-template-columns:minmax(0,1fr);min-width:0}
.att-list-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-weight:600}
.att-row{display:flex;align-items:center;justify-content:space-between;gap:.8rem;min-width:0;flex-wrap:wrap}
.att-remove{display:inline-flex!important;align-items:center;gap:.35rem;font-size:.78rem;color:var(--muted);white-space:nowrap;font-weight:500}
.att-remove input{width:auto;margin:0}
input[type=file]{padding:.5rem;font-size:.85rem}
input[type=file]::file-selector-button{background:var(--panel-2);border:1px solid var(--line-2);color:var(--ink);
  border-radius:8px;padding:.45rem .8rem;margin-right:.7rem;cursor:pointer;font-family:inherit;font-size:.82rem}
input[type=file]::file-selector-button:hover{border-color:var(--accent)}

/* ---- Expenses inside the job drawer ---- */
/* minmax(0,…) + min-width:0 stop a long expense/attachment label forcing the
   grid track wider than the drawer on narrow phones (grid items default to
   min-width:auto). */
.job-expenses{display:grid;gap:.9rem;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:.9rem;
  grid-template-columns:minmax(0,1fr)}
.job-expenses > *{min-width:0}
.job-expenses .att-list{background:var(--panel);}
.je-hint{margin:-.3rem 0 -.2rem}
.je-total{border-top:1px solid var(--line);padding-top:.45rem;margin-top:.15rem}
.je-link summary{cursor:pointer;font-size:.82rem;color:var(--ink-dim);font-weight:600;padding:.3rem 0}
.je-link summary:hover{color:var(--accent)}
.je-link .att-list{margin-top:.5rem;max-height:220px;overflow-y:auto}
.je-pick{display:flex!important;align-items:center;gap:.6rem;font-size:.82rem;color:var(--ink-dim);font-weight:500;cursor:pointer;min-width:0}
.je-pick span{min-width:0;overflow-wrap:anywhere}
.je-pick input{width:auto;margin:0;flex:0 0 auto}

/* ---- Invoice line-item editor ---- */
.inv-line-editor{display:grid;gap:.6rem;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:.9rem}
.inv-line-rows{display:grid;gap:.5rem}
.inv-line-row{display:flex;gap:.5rem;align-items:center}
.inv-line-row input[name="line_desc[]"]{flex:1 1 auto;min-width:0}
.inv-line-row input[name="line_amount[]"]{flex:0 0 7rem;min-width:0}
.inv-line-remove{flex:0 0 auto;width:38px;height:38px;margin-top:.35rem;border-radius:8px;border:1px solid var(--line);
  background:var(--panel-2);color:var(--muted);cursor:pointer;font-size:.9rem;font-family:inherit;transition:.15s}
.inv-line-remove:hover{color:#ffb1b1;border-color:var(--danger)}
/* JS toggles this when only one row remains — can't leave zero rows. */
.inv-line-editor.is-single .inv-line-remove{visibility:hidden}

/* Overdue */
.tag-overdue{background:rgba(232,91,91,.22);color:#ffb1b1;font-weight:700}
.tag-deposit{background:rgba(103,150,245,.22);color:#b7cdff;font-weight:700}

/* ---- Calendar subscribe panel ---- */
.feed-panel{margin-top:.4rem}
.feed-url-label{display:block;font-size:.8rem;color:var(--ink-dim);font-weight:600;margin:1rem 0 .8rem}
.feed-url{display:flex;gap:.5rem;margin-top:.35rem}
.feed-url input{margin-top:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8rem;min-width:0}
.feed-actions{display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}
.feed-actions form{margin:0}
.feed-warn{margin-top:1rem;padding-top:.9rem;border-top:1px solid var(--line)}
.feed-warn strong{color:var(--warn)}

/* ---- Jobs filter (Live / Invoiced / All) and Invoices filter (Outstanding /
   Paid / All) — both reuse the segmented .cal-views pill control ---- */
.job-filter .filter-n,.invoice-filter .filter-n{margin-left:.35rem;background:var(--bg-2);border:1px solid var(--line);border-radius:99px;
  padding:0 .35rem;font-size:.7rem;font-weight:700;min-width:1.15rem;display:inline-block;text-align:center}
.job-filter a.on .filter-n,.invoice-filter a.on .filter-n{background:var(--grad);color:#1a0f00;border-color:transparent}
@media(max-width:560px){.job-filter,.invoice-filter{width:100%}.job-filter a,.invoice-filter a{flex:1;justify-content:center}}

/* ---- Admin ---- */
.admin-tabs{margin-bottom:1.4rem}
/* the inline "reset password" form sits in a card action row */
.card-actions input[type=text]{background:var(--bg-2);border:1px solid var(--line);border-radius:8px;
  color:var(--ink);min-width:0;max-width:11rem}
.card-actions form{gap:.4rem;align-items:center}

/* ---- Settings ---- */
.settings-grid{max-width:560px}
.settings-grid .panel h2{font-size:1.05rem;margin-bottom:.2rem}
.small{font-size:.82rem}

@media(max-width:900px){.panel-row{grid-template-columns:1fr}.kpi-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.kpi-wide{grid-column:span 3}}

/* ---- Phone layout ---- */
@media(max-width:700px){
  .portal-top{gap:.5rem .8rem;padding:.65rem .9rem}
  .portal-brand{font-size:1.05rem}
  /* nav drops to its own row and scrolls sideways — no cramped wrapping */
  .portal-nav{order:3;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin-right:0}
  .portal-nav::-webkit-scrollbar{display:none}
  .portal-nav a{white-space:nowrap;padding:.45rem .8rem}
  .profile{order:2;margin-left:auto}
  /* Clamp to the viewport so a narrow phone can't push the menu off-screen. */
  .profile-menu{right:0;min-width:0;width:min(260px,calc(100vw - 1.8rem))}
  .portal-main{padding:1rem .9rem 5.5rem} /* extra bottom space so the FAB never covers content */
  /* 100% (not 100vw): vw ignores the scrollbar and can exceed the visual
     viewport on iOS, which made the open editor scroll sideways. The drawer
     is position:fixed;inset:0, so 100% is exactly the viewport. */
  .drawer-inner{width:100%;border-left:0} /* editor goes full-screen on phones */
  table.data{min-width:640px}
  .cal-grid{gap:4px}
  .cal-cell{min-height:68px;padding:.3rem}
  .cal-chip{font-size:.66rem}
}
@media(max-width:560px){
  .kpi-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem}
  .kpi{padding:.85rem .9rem}
  .kpi-val{font-size:1.25rem}
  .kpi-wide{grid-column:span 2}
  .grid-2{grid-template-columns:minmax(0,1fr)}
  .page-head{align-items:flex-start}
  .page-head h1{font-size:1.45rem}
  .bars{height:150px;gap:.28rem}
  .bar-x{font-size:.58rem}
  .head-actions{width:100%}
  .head-actions .btn{flex:1;justify-content:center}
  .msg-actions{gap:.8rem}
  .btn{padding:.75rem 1.1rem} /* comfier tap targets */
  /* Month grid on phones: chips are unreadable at this size, so show a tappable
     job-count pill instead — tap a day to open the readable Day view. */
  .cal-cell{min-height:58px;align-items:flex-start;gap:.2rem}
  .cal-chips{display:none}
  .cal-daycount{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;
    padding:0 .32rem;border-radius:99px;background:var(--grad);color:#1a0f00;font-size:.7rem;font-weight:700}
  .cal-views{width:100%;justify-content:space-between}
  .cal-views a{flex:1;justify-content:center;padding:.35rem .4rem}
  .cal-day-head{padding:.5rem .7rem}
  .cal-entry{padding:.55rem .6rem;gap:.55rem}
}

/* ---- Projects (list cards, detail page, tasks) ---- */
.back-link{display:inline-block;font-size:.82rem;color:var(--muted);font-weight:600;margin-bottom:.35rem}
/* Legal name under a client's display_name on their own page (17 Aug 2026) —
   same "big nickname, tiny legal name" idea as .sub-legal on cards. */
.h1-legal{display:block;font-family:'Inter',sans-serif;font-size:.85rem;font-weight:500;color:var(--muted);letter-spacing:0;margin-top:.15rem}
.back-link:hover{color:var(--accent)}
.card-title a:hover{color:var(--accent)}
.btn-act.is-static{cursor:default;color:var(--muted)}
.btn-act.is-static:hover{color:var(--muted);border-color:var(--line)}

/* Progress bars — budget usage and task completion */
.proj-bars{display:grid;gap:.6rem}
.proj-bar-head{display:flex;justify-content:space-between;gap:.6rem;font-size:.76rem;color:var(--muted);font-weight:600;margin-bottom:.3rem}
.bar{height:7px;background:var(--bg-2);border:1px solid var(--line);border-radius:99px;overflow:hidden}
.bar span{display:block;height:100%;background:var(--grad);border-radius:99px}
.bar span.ok{background:var(--ok)}
.bar span.over{background:var(--danger)}
.proj-progress{display:grid;gap:1rem;margin-bottom:1.4rem}
/* The detail page's KPI row: 6 tiles is too tight for these labels */
.proj-kpis{grid-template-columns:repeat(3,minmax(0,1fr))}
.proj-kpis .kpi-sub{color:var(--muted);font-weight:500}

/* Task checklist */
.task-add{display:flex;gap:.6rem;align-items:flex-start;flex-wrap:wrap}
.task-add input[type=text]{flex:1 1 240px;margin-top:0}
.task-add input[type=date]{flex:0 1 170px;margin-top:0}
.task-add button{flex:0 0 auto;margin-top:0}
.task-list{list-style:none;margin-top:1rem;display:grid;gap:.4rem}
.task{display:flex;align-items:center;gap:.6rem;background:var(--bg-2);border:1px solid var(--line);
  border-radius:10px;padding:.5rem .7rem}
.task form{display:flex}
.task-check,.task-x{background:none;border:0;color:var(--ink-dim);cursor:pointer;font-size:1.05rem;line-height:1;padding:.15rem .25rem}
.task-check:hover{color:var(--accent)}
.task-x{color:var(--muted);font-size:.85rem}
.task-x:hover{color:var(--danger)}
.task-title{flex:1;min-width:0;overflow-wrap:anywhere;font-size:.92rem}
.task.is-done .task-title{text-decoration:line-through;color:var(--muted)}
.task-due{font-size:.76rem;color:var(--muted);white-space:nowrap}
.task-due.is-overdue{color:#ffb1b1;font-weight:700}

/* Linked jobs / invoices / expenses rows on the project page */
.link-list{display:grid;gap:.4rem;margin-top:.2rem}
.link-row{display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;background:var(--bg-2);border:1px solid var(--line);
  border-radius:10px;padding:.55rem .7rem}
.link-main{flex:1 1 220px;min-width:0;font-size:.92rem;overflow-wrap:anywhere}
.link-main .muted{display:block;font-size:.78rem;margin-top:.1rem}
.link-main a:hover{color:var(--accent)}
.link-amount{font-weight:600;font-size:.92rem;white-space:nowrap}
.link-amount.owed{color:var(--warn)}
.link-via{font-size:.72rem;white-space:nowrap}
.link-row form{display:flex}
.link-row .btn-act{min-height:32px;padding:.25rem .6rem;font-size:.78rem}
.link-actions{margin-top:.8rem;display:flex;gap:.6rem;flex-wrap:wrap}

@media(max-width:900px){
  .proj-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
  .proj-kpis .kpi-wide{grid-column:span 2}
}
@media(max-width:560px){
  .proj-kpis{grid-template-columns:1fr 1fr}
  .task-add input[type=date]{flex:1 1 130px}
}

/* ---- Client detail page ---- */
.sub-head{margin-top:1.6rem;margin-bottom:.9rem}
.sub-head h2{font-size:1.15rem}
.client-meta-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:1rem;margin-bottom:1.4rem}
.client-meta{padding:1rem 1.15rem;font-size:.9rem;color:var(--ink-dim)}
.client-meta .kpi-label{display:block;margin-bottom:.35rem}

/* ---- Clickable cards: the card IS the object you open ---- */
.card[data-card-open]{cursor:pointer}
.card[data-card-open]:hover{border-color:var(--accent);transform:translateY(-1px);
  box-shadow:0 6px 20px rgba(0,0,0,.28)}
.card[data-card-open]:active{transform:translateY(0)}
/* The title is the real link (keyboard/screen-reader route into the object) */
.card[data-card-open] .card-title a{color:inherit}
.card[data-card-open]:hover .card-title a{color:var(--accent)}
.card[data-card-open] .card-title a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}
/* Buttons inside a clickable card must still feel like the foreground layer */
.card[data-card-open] .card-actions{position:relative;z-index:1}
/* Secondary rows (project/client pages) are clickable objects too */
.link-row[data-card-open]{cursor:pointer}
.link-row[data-card-open]:hover{border-color:var(--accent);background:var(--panel-2)}
.link-row[data-card-open] .link-main a{color:inherit}
.link-row[data-card-open]:hover .link-main a{color:var(--accent)}
