/* =====================================================================
   Prepd — design system
   Palette + type aligned with the Session Plan PDF for one cohesive brand.
   ===================================================================== */
/* General Sans is the UI face. It has to come from Fontshare's CDN: their EULA permits use
   "in any media (including Print, Web, Mobile, Digital, Apps)" but forbids "uploading them in
   a public server" or transmitting the font software "over the Internet in font serving", so
   self-hosting it would breach the licence. Which leaves the CDN as a single point of failure,
   hence the fallback below. */
@import url('https://api.fontshare.com/v2/css?f[]=general-sans@400,500,600,700&display=swap');

/* DM Sans, SELF-HOSTED, is the fallback — it is second in every family stack below.
   It used to come from Google Fonts, so a Fontshare outage fell back to a *second* CDN and a
   total outage (or an installed PWA with no connection) fell back to whatever the device had.
   The OFL explicitly grants the right to "use, study, copy, merge, embed, modify, redistribute",
   so unlike General Sans this one can live in the repo; the licence sits beside it in
   web/fonts/DMSans-OFL.txt. Two files, both variable across the whole weight range, split only
   by the character sets we need. */
@font-face{
  font-family:'DM Sans';font-style:normal;font-weight:100 1000;font-display:swap;
  src:url('../fonts/dmsans-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'DM Sans';font-style:normal;font-weight:100 1000;font-display:swap;
  src:url('../fonts/dmsans-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

:root{
  /* brand */
  --navy:#0f2137; --navy-700:#16304d; --navy-600:#1e3a5f; --navy-500:#2a4a6f;
  --navy-soft:#1b3556;
  --brand:#C0392B; --brand-600:#a93226; --brand-soft:#fdecea;
  --blue:#1d4ed8; --blue-600:#1746c4; --blue-soft:#eef3ff;
  --green:#15803d; --green-soft:#f0fdf4;
  --amber:#b45309; --amber-soft:#fffbeb;
  --teal:#0e7490; --teal-soft:#f0fdfa;
  --indigo:#5b21b6; --indigo-soft:#f5f3ff;
  --red:#dc2626; --red-soft:#fef2f2;
  /* extended accents — more colour variety (crimson, gold, pastels) */
  --crimson:#be123c; --crimson-soft:#fff1f4;
  --gold:#b08900; --gold-soft:#fdf6db;
  --pink:#be185d; --pink-soft:#fdf2f8;
  --violet:#7c3aed; --violet-soft:#f5f1ff;
  --cyan:#0891b2; --cyan-soft:#ecfeff;
  --lime:#4d7c0f; --lime-soft:#f7fee7;
  /* neutrals */
  --ink:#1f2937; --muted:#64748b; --faint:#94a3b8;
  --line:#e4e8ef; --line-2:#eef1f6;
  --bg:#f5f7fa; --card:#ffffff;
  /* shape */
  --r-sm:7px; --r:11px; --r-lg:16px; --r-pill:999px;
  --sh-1:0 1px 2px rgba(15,33,55,.06), 0 1px 3px rgba(15,33,55,.05);
  --sh-2:0 4px 14px rgba(15,33,55,.08);
  --sh-3:0 12px 34px rgba(15,33,55,.14);
  --sb-w:252px;
  --ease:cubic-bezier(.4,0,.2,1);
}

*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:74px}
body{
  font-family:'General Sans','DM Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  color:var(--ink); background:var(--bg); line-height:1.55;
  font-size:14px; -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
img,svg{display:block}
button{font-family:inherit;cursor:pointer}
input,textarea,select{font-family:'General Sans','DM Sans',-apple-system,'Segoe UI',Roboto,sans-serif;letter-spacing:-.1px}/* crisp UI font where operators type */
::selection{background:#cfe0ff}

/* ---------- logo ---------- */
.logo{font-weight:800;letter-spacing:-.5px;font-size:22px;color:var(--navy)}
.logo .dot{color:#e5484d;margin-left:1px}
.logo.on-dark{color:#fff}
/* stacked wordmark: "prepd." over "education" */
.logo-stack{display:inline-flex;flex-direction:column;line-height:.86;align-items:flex-start}
.logo-stack .logo-ed{font-size:.4em;font-weight:600;letter-spacing:.34em;text-transform:uppercase;color:var(--muted);margin-top:3px}
.logo.on-dark .logo-ed{color:rgba(255,255,255,.6)}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:40px;padding:0 16px;border:1px solid transparent;border-radius:var(--r);
  font-weight:600;font-size:13.5px;transition:.16s var(--ease);white-space:nowrap}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--blue);color:#fff}
.btn-primary:hover{background:var(--blue-600)}
.btn-brand{background:var(--brand);color:#fff}
.btn-brand:hover{background:var(--brand-600)}
.btn-dark{background:var(--navy);color:#fff}
.btn-dark:hover{background:var(--navy-700)}
.btn-ghost{background:#fff;color:var(--ink);border-color:var(--line)}
.btn-ghost:hover{background:var(--bg);border-color:#d3dae6}
.btn-soft{background:var(--blue-soft);color:var(--blue)}
.btn-soft:hover{background:#e3ecff}
.btn-lg{height:46px;padding:0 22px;font-size:15px}
.btn-sm{height:32px;padding:0 12px;font-size:12.5px;border-radius:var(--r-sm)}
.btn-block{width:100%}
.btn[disabled]{opacity:.55;cursor:not-allowed}

/* ---------- badges / pills ---------- */
.badge{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;
  border-radius:var(--r-pill);font-size:11px;font-weight:700;letter-spacing:.2px}
.badge-blue{background:var(--blue-soft);color:var(--blue)}
.badge-green{background:var(--green-soft);color:var(--green)}
.badge-amber{background:var(--amber-soft);color:var(--amber)}
.badge-red{background:var(--red-soft);color:var(--red)}
.badge-navy{background:#e8edf5;color:var(--navy)}
.badge-crimson{background:var(--crimson-soft);color:var(--crimson)}
.badge-gold{background:var(--gold-soft);color:var(--gold)}
.badge-pink{background:var(--pink-soft);color:var(--pink)}
.badge-violet{background:var(--violet-soft);color:var(--violet)}
.badge-cyan{background:var(--cyan-soft);color:var(--cyan)}
.badge-lime{background:var(--lime-soft);color:var(--lime)}
.dotmark{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}

/* ---------- avatar ---------- */
.avatar{width:38px;height:38px;border-radius:50%;background:var(--navy);color:#fff;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;flex:none;
  background-image:linear-gradient(135deg,var(--navy-600),var(--navy))}
.avatar.sm{width:30px;height:30px;font-size:12px}
.avatar.lg{width:52px;height:52px;font-size:18px}

/* =====================================================================
   APP SHELL  (sidebar + main)
   ===================================================================== */
.app{display:flex;min-height:100vh;min-height:100dvh}   /* dvh: 100vh is wrong on iOS Safari */
/* The sidebar MUST scroll: the owner nav is 20 items and does not fit a phone screen.
   Safe-area padding keeps the last item clear of the iPhone home indicator when installed. */
.sidebar{position:fixed;inset:0 auto 0 0;width:var(--sb-w);background:var(--navy);
  color:#fff;display:flex;flex-direction:column;z-index:40;
  padding:20px 14px calc(20px + env(safe-area-inset-bottom,0px)) calc(14px + env(safe-area-inset-left,0px));
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.sidebar::-webkit-scrollbar{width:0}          /* scrolls, but no scrollbar over the navy */
.sidebar .brand{display:flex;align-items:center;gap:8px;padding:6px 10px 18px}
.nav{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.nav-label{font-size:10px;font-weight:700;letter-spacing:1.4px;text-transform:uppercase;
  color:rgba(255,255,255,.38);padding:14px 12px 6px}
.nav a{display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:var(--r);
  color:rgba(255,255,255,.74);font-weight:600;font-size:13.5px;transition:.14s var(--ease)}
.nav a svg{width:18px;height:18px;opacity:.85;flex:none}
.nav a:hover{background:rgba(255,255,255,.07);color:#fff}
.nav a.active{background:var(--blue);color:#fff}
.nav a.active svg{opacity:1}
.nav a .nav-badge{margin-left:auto;min-width:18px;height:18px;padding:0 5px;border-radius:9px;
  background:#ef4444;color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1}
.sidebar .sb-foot{margin-top:auto;padding-top:14px}
.sb-card{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);
  border-radius:var(--r);padding:13px 14px}
.sb-card h4{font-size:13px;margin-bottom:3px}
.sb-card p{font-size:11.5px;color:rgba(255,255,255,.6);margin-bottom:10px;line-height:1.5}

.main{flex:1;margin-left:var(--sb-w);min-width:0;max-width:100%;display:flex;flex-direction:column}
.topbar{position:sticky;top:0;z-index:30;background:rgba(255,255,255,.86);
  backdrop-filter:saturate(1.4) blur(8px);border-bottom:1px solid var(--line);
  display:flex;align-items:center;gap:16px;min-width:0;
  padding:13px calc(28px + env(safe-area-inset-right,0px)) 13px calc(28px + env(safe-area-inset-left,0px))}
/* the title block must be allowed to shrink, or its min-content width widens the whole
   layout viewport and iOS zooms the entire app out to fit */
.topbar > div{min-width:0}
.topbar .pagetitle{font-size:18px;font-weight:800;letter-spacing:-.3px}
.topbar .sub{font-size:12.5px;color:var(--muted);margin-top:1px}
.topbar .spacer{flex:1}
.searchbox{display:flex;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--line);
  border-radius:var(--r-pill);padding:0 14px;height:38px;width:280px;max-width:34vw;color:var(--muted)}
.searchbox input{border:0;background:transparent;outline:0;font-size:13.5px;width:100%;color:var(--ink)}
.iconbtn{width:38px;height:38px;flex:none;border-radius:var(--r);border:1px solid var(--line);background:#fff;
  display:flex;align-items:center;justify-content:center;color:var(--muted);position:relative}
.iconbtn:hover{background:var(--bg)}
/* Refresh: in the top bar of every page (app.js mountRefresh), and the target of the
   pull-down gesture below. The installed app has no address bar, so without these there is
   no way to reload it. */
.refresh-btn{color:var(--muted)}
.refresh-btn:hover{color:var(--navy)}
.refresh-btn.spinning svg{animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.ptr{position:fixed;top:0;left:0;right:0;display:flex;justify-content:center;z-index:31;
  pointer-events:none;opacity:0;transform:translateY(-46px);
  transition:transform .2s var(--ease),opacity .2s var(--ease)}
.ptr.on{opacity:1}
.ptr .ptr-dot{margin-top:calc(6px + env(safe-area-inset-top,0px));width:36px;height:36px;border-radius:50%;
  background:#fff;border:1px solid var(--line);box-shadow:var(--sh-2);color:var(--muted);
  display:flex;align-items:center;justify-content:center;transition:color .15s,border-color .15s}
.ptr.ready .ptr-dot{color:var(--blue);border-color:var(--blue)}
.ptr.going .ptr-dot svg{animation:spin .7s linear infinite}
@media(prefers-reduced-motion:reduce){.refresh-btn.spinning svg,.ptr.going .ptr-dot svg{animation:none}}
.iconbtn .dotnotif{position:absolute;top:8px;right:9px;width:7px;height:7px;border-radius:50%;
  background:var(--brand);border:2px solid #fff}
.userchip{display:flex;align-items:center;gap:10px;padding:5px 6px 5px 5px;border-radius:var(--r-pill);
  border:1px solid var(--line);background:#fff}
.userchip:hover{background:var(--bg)}
.userchip .who{line-height:1.2}
.userchip .who b{font-size:13px;display:block}
.userchip .who span{font-size:11px;color:var(--muted)}

.content{padding:26px 28px calc(48px + env(safe-area-inset-bottom,0px));max-width:1280px;width:100%;min-width:0}

/* ---------- generic section heads ---------- */
.row{display:flex;align-items:center;gap:12px}
.section-h{display:flex;align-items:center;gap:12px;margin:6px 0 14px}
.section-h h2{font-size:16px;font-weight:800;letter-spacing:-.2px}
.section-h .spacer{flex:1}
.link{color:var(--blue);font-weight:700;font-size:13px}
.link:hover{text-decoration:underline}

/* ---------- cards ---------- */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1)}
.card.pad{padding:18px}

/* stat cards */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.stat{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:16px 18px;box-shadow:var(--sh-1);position:relative;overflow:hidden}
.stat .ic{width:38px;height:38px;border-radius:11px;display:flex;align-items:center;justify-content:center;margin-bottom:12px}
.stat .ic svg{width:20px;height:20px}
.stat .ic.stepnum{font-weight:800;font-size:18px;font-variant-numeric:tabular-nums}
.stat .k{font-size:27px;font-weight:800;letter-spacing:-.6px;line-height:1}
.stat .l{font-size:12.5px;color:var(--muted);margin-top:5px}
.stat .trend{position:absolute;top:16px;right:16px;font-size:11.5px;font-weight:700}
.ic-blue{background:var(--blue-soft);color:var(--blue)}
.ic-green{background:var(--green-soft);color:var(--green)}
.ic-amber{background:var(--amber-soft);color:var(--amber)}
.ic-indigo{background:var(--indigo-soft);color:var(--indigo)}
.ic-crimson{background:var(--crimson-soft);color:var(--crimson)}
.ic-gold{background:var(--gold-soft);color:var(--gold)}
.ic-pink{background:var(--pink-soft);color:var(--pink)}
.ic-violet{background:var(--violet-soft);color:var(--violet)}
.ic-cyan{background:var(--cyan-soft);color:var(--cyan)}
.ic-lime{background:var(--lime-soft);color:var(--lime)}
.up{color:var(--green)} .down{color:var(--red)}

/* two-column dashboard grid */
.grid-2{display:grid;grid-template-columns:1.6fr 1fr;gap:20px;margin-top:22px;align-items:start}

/* session rows */
.sessions{display:flex;flex-direction:column}
.session{display:flex;align-items:center;gap:15px;padding:14px 4px;border-top:1px solid var(--line-2)}
.session:first-child{border-top:0}
.when{width:58px;text-align:center;flex:none}
.when .d{font-size:20px;font-weight:800;line-height:1}
.when .m{font-size:10.5px;font-weight:700;color:var(--brand);text-transform:uppercase;letter-spacing:.6px}
.session .meta{flex:1;min-width:0}
.session .meta h4{font-size:14px;font-weight:700}
.session .meta p{font-size:12.5px;color:var(--muted);display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:2px}
.session .meta p .i{display:inline-flex;align-items:center;gap:5px}
.subject-tag{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;
  padding:3px 9px;border-radius:var(--r-pill)}

/* plan (pdf) cards */
.plans{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px}
.plan{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:#fff;transition:.16s var(--ease)}
.plan:hover{box-shadow:var(--sh-2);transform:translateY(-2px)}
.plan .thumb{height:96px;background:linear-gradient(135deg,var(--navy-600),var(--navy));
  color:#fff;padding:12px;display:flex;flex-direction:column;justify-content:space-between}
.plan .thumb .t{font-size:12px;font-weight:700;line-height:1.3}
.plan .thumb .b{font-size:10px;color:rgba(255,255,255,.6)}
.plan .pmeta{padding:10px 12px}
.plan .pmeta h5{font-size:12.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.plan .pmeta span{font-size:11px;color:var(--muted)}

/* mini list */
.minilist{display:flex;flex-direction:column;gap:2px}
.mini{display:flex;align-items:center;gap:12px;padding:10px 8px;border-radius:var(--r)}
.mini:hover{background:var(--bg)}
.mini .meta{flex:1;min-width:0}
.mini .meta b{font-size:13px;display:block}
.mini .meta span{font-size:11.5px;color:var(--muted)}

/* progress bar */
.bar{height:8px;border-radius:99px;background:var(--line);overflow:hidden}
.bar>i{display:block;height:100%;border-radius:99px;background:var(--blue)}

/* =====================================================================
   CALENDAR / BOOKING
   ===================================================================== */
.book-grid{display:grid;grid-template-columns:1.5fr 1fr;gap:20px;align-items:start}
.cal-head{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.cal-head h3{font-size:16px;font-weight:800}
.cal-head .spacer{flex:1}
.cal{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.cal .dow{font-size:11px;font-weight:700;color:var(--faint);text-align:center;padding:4px 0;text-transform:uppercase;letter-spacing:.5px}
.day{aspect-ratio:1/1;border:1px solid var(--line);border-radius:var(--r);background:#fff;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  font-weight:600;font-size:14px;color:var(--ink);transition:.12s var(--ease);position:relative}
.day:hover:not(.empty):not(.past){border-color:var(--blue);background:var(--blue-soft)}
.day.empty{border:0;background:transparent;cursor:default}
.day.past{color:var(--faint);background:var(--bg);cursor:not-allowed}
.day.today{border-color:var(--brand);color:var(--brand);font-weight:800}
.day.selected{background:var(--blue);color:#fff;border-color:var(--blue)}
.day .av{display:flex;gap:3px}
.day .av i{width:5px;height:5px;border-radius:50%;background:var(--green)}
.day.selected .av i{background:rgba(255,255,255,.9)}
.day.none .av{display:none}

.slots-panel{position:sticky;top:84px}
.slots-panel .ph{color:var(--muted);font-size:13px;text-align:center;padding:30px 10px}
.slots{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:4px}
.slot{height:40px;border:1px solid var(--line);border-radius:var(--r);background:#fff;
  font-weight:600;font-size:13px;color:var(--ink);transition:.12s var(--ease)}
.slot:hover{border-color:var(--blue);color:var(--blue);background:var(--blue-soft)}
.slot.sel{background:var(--blue);color:#fff;border-color:var(--blue)}
.slot[disabled]{color:var(--faint);background:var(--bg);text-decoration:line-through;cursor:not-allowed}

/* =====================================================================
   FORMS / AUTH
   ===================================================================== */
.field{margin-bottom:14px}
.field label{display:block;font-size:12.5px;font-weight:700;margin-bottom:6px;color:var(--navy)}
.input{width:100%;height:44px;border:1px solid var(--line);border-radius:var(--r);
  padding:0 14px;font-size:14px;outline:0;background:#fff;transition:.14s var(--ease)}
.input:focus{border-color:var(--blue);box-shadow:0 0 0 3px var(--blue-soft)}
/* line-height is pinned so the min-height can be a whole number of lines: at 90px with 12px of
   padding the box held 3.14 lines, so every textarea with more text than that sliced the fourth
   one across the bottom edge — which reads as broken rather than as "scroll for more". */
textarea.input{height:auto;padding:12px 14px;resize:vertical;line-height:1.5;min-height:calc(1.5em * 4 + 26px)}
/* styled select — custom chevron instead of the plain native control */
select.input{appearance:none;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;padding-right:36px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 13px center}
.hint{font-size:11.5px;color:var(--muted);margin-top:6px}
.formrow{display:grid;grid-template-columns:1fr 1fr;gap:12px}

.auth{min-height:100vh;display:grid;grid-template-columns:1.05fr 1fr}
.auth-aside{background:var(--navy);color:#fff;padding:46px 52px;display:flex;flex-direction:column;
  position:relative;overflow:hidden}
.auth-aside::after{content:"";position:absolute;right:-120px;bottom:-120px;width:340px;height:340px;
  border-radius:50%;background:radial-gradient(circle,rgba(192,57,43,.32),transparent 70%)}
.auth-aside .brand{margin-bottom:auto}
.auth-aside h1{font-size:34px;font-weight:800;letter-spacing:-.8px;line-height:1.15;margin:0 0 14px}
.auth-aside p.lede{font-size:15px;color:rgba(255,255,255,.72);max-width:42ch;line-height:1.6}
.auth-feats{display:flex;flex-direction:column;gap:14px;margin-top:30px}
.auth-feat{display:flex;gap:12px;align-items:flex-start;font-size:13.5px;color:rgba(255,255,255,.84)}
.auth-feat .tick{width:24px;height:24px;border-radius:7px;background:rgba(255,255,255,.1);
  color:#7fffb0;display:flex;align-items:center;justify-content:center;flex:none;font-weight:800}
.auth-quote{margin-top:34px;font-size:13px;color:rgba(255,255,255,.62);border-left:2px solid var(--brand);padding-left:14px;z-index:1}

.auth-main{display:flex;align-items:center;justify-content:center;padding:40px 24px}
.auth-card{width:100%;max-width:392px}
.auth-card h2{font-size:24px;font-weight:800;letter-spacing:-.4px}
.auth-card .muted{color:var(--muted);font-size:13.5px;margin-top:4px;margin-bottom:22px}
.tabs{display:flex;background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:4px;margin-bottom:22px}
.tabs button{flex:1;height:34px;border:0;background:transparent;border-radius:8px;font-weight:700;font-size:13px;color:var(--muted)}
.tabs button.on{background:#fff;color:var(--navy);box-shadow:var(--sh-1)}
.rolepick{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:18px}
.role{border:1px solid var(--line);border-radius:var(--r);padding:12px;text-align:left;background:#fff;transition:.14s var(--ease)}
.role:hover{border-color:#cbd5e1}
.role.on{border-color:var(--blue);background:var(--blue-soft);box-shadow:0 0 0 3px rgba(29,78,216,.08)}
.role .ic{width:30px;height:30px;border-radius:8px;background:var(--blue-soft);color:var(--blue);
  display:flex;align-items:center;justify-content:center;margin-bottom:8px}
.role.on .ic{background:var(--blue);color:#fff}
.role b{font-size:13px;display:block}
.role span{font-size:11px;color:var(--muted)}
.oauth{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:16px}
.divider{display:flex;align-items:center;gap:12px;color:var(--faint);font-size:11.5px;margin:18px 0}
.divider::before,.divider::after{content:"";flex:1;height:1px;background:var(--line)}
.checkrow{display:flex;align-items:center;justify-content:space-between;font-size:12.5px;margin:-2px 0 18px}
.checkrow label{display:flex;align-items:center;gap:8px;color:var(--muted)}

/* =====================================================================
   LANDING
   ===================================================================== */
.lp-nav{position:sticky;top:0;z-index:50;background:rgba(245,247,250,.88);backdrop-filter:saturate(180%) blur(10px);border-bottom:1px solid var(--line)}
.lp-nav-inner{display:flex;align-items:center;gap:18px;padding:14px 40px;max-width:1180px;margin:0 auto}
@media(max-width:720px){.lp-nav-inner{gap:10px;padding:12px 18px}.lp-nav .navlink{display:none}}
.lp-nav .spacer{flex:1}
.lp-nav a.navlink{font-size:14px;font-weight:600;color:var(--muted)}
.lp-nav a.navlink:hover{color:var(--ink)}
.hero{max-width:1180px;margin:0 auto;padding:64px 40px;display:grid;grid-template-columns:1.1fr 1fr;gap:50px;align-items:center}
.hero .eyebrow{display:inline-flex;align-items:center;gap:8px;background:var(--brand-soft);color:var(--brand);
  font-weight:700;font-size:12px;padding:5px 12px;border-radius:var(--r-pill);margin-bottom:18px}
.hero h1{font-size:48px;font-weight:800;letter-spacing:-1.4px;line-height:1.05}
.hero h1 em{font-style:normal;color:var(--blue)}
.hero p.lede{font-size:17px;color:var(--muted);margin:18px 0 26px;max-width:48ch;line-height:1.6}
.hero .cta{display:flex;gap:12px;flex-wrap:wrap}
.hero .proof{display:flex;flex-wrap:wrap;gap:18px 26px;margin-top:30px}
.hero .proof>div{flex:1 1 150px;min-width:0}
.hero .proof .k{font-size:16px;font-weight:800}
.hero .proof .l{font-size:12px;color:var(--muted);line-height:1.45}
.hero-art{position:relative;min-height:480px}
/* real Session Plan PDF preview — two actual generated pages, framed + offset (sized by height so A4 portrait can't overflow) */
.pdf-stack{position:relative;width:400px;max-width:100%;height:460px;margin:14px auto 0;animation:pdfFloat 7s ease-in-out infinite}
.pdf-stack::before{content:"";position:absolute;inset:4% 2% 2%;background:radial-gradient(120% 80% at 50% 0,var(--blue-soft),transparent 70%);filter:blur(10px);z-index:0}
.pdf-pg{position:absolute;border-radius:10px;border:1px solid #e6eaf0;background:#fff;box-shadow:0 32px 70px -24px rgba(15,33,55,.42);transition:transform .55s cubic-bezier(.22,1,.36,1)}
.pdf-cover{height:82%;width:auto;right:10px;top:4px;z-index:1;transform:rotate(4deg)}
.pdf-content{height:96%;width:auto;left:10px;top:18px;z-index:2;transform:rotate(-2.5deg)}
.pdf-stack:hover .pdf-cover{transform:rotate(6deg) translate(16px,-6px)}
.pdf-stack:hover .pdf-content{transform:rotate(-4deg) translate(-16px,-2px)}
@keyframes pdfFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-12px)}}
@media(prefers-reduced-motion:reduce){.pdf-stack{animation:none}}
.pdf-tag{position:absolute;left:50%;bottom:-10px;transform:translateX(-50%);white-space:nowrap;z-index:3;
  font-size:11.5px;font-weight:600;color:var(--muted);background:#fff;border:1px solid var(--line);
  border-radius:99px;padding:5px 13px;box-shadow:var(--sh-1)}
/* landing — contact band */
.contact-band{background:linear-gradient(160deg,var(--navy),var(--navy-600));color:#fff;margin-top:8px}
.contact-inner{max-width:760px;margin:0 auto;padding:60px 40px;text-align:center}
.contact-band h2{font-size:30px;font-weight:800;letter-spacing:-.7px;margin:14px 0 10px}
.contact-band p{color:rgba(255,255,255,.78);font-size:16px;line-height:1.6;max-width:48ch;margin:0 auto}
.btn-onnavy{background:rgba(255,255,255,.1);color:#fff;border:1px solid rgba(255,255,255,.22)}
.btn-onnavy:hover{background:rgba(255,255,255,.18);color:#fff}
/* landing — contact form card */
.contact-form{max-width:520px;margin:24px auto 0;background:#fff;color:var(--ink);border-radius:16px;padding:20px;
  box-shadow:0 34px 80px -34px rgba(0,0,0,.55);text-align:left;display:flex;flex-direction:column;gap:12px;position:relative}
.contact-form .cf-row{display:flex;gap:12px}
.contact-form .cf-row .input{flex:1;min-width:0}
.contact-form .cf-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-top:2px}
.contact-form .cf-actions .btn{flex:1;white-space:nowrap}
.cf-note{font-size:12.5px;color:var(--muted);text-align:center;margin:4px 0 0}
.cf-note a{color:var(--blue);font-weight:600}
@media(max-width:560px){.contact-form .cf-row{flex-direction:column}.contact-form .cf-actions{flex-direction:column}.contact-form .cf-actions .btn{width:100%}}
/* landing — lesson-planner band */
.planner-band{background:linear-gradient(160deg,var(--navy),var(--navy-600));color:#fff;margin-top:24px}
.planner-inner{max-width:1180px;margin:0 auto;padding:56px 40px;display:grid;grid-template-columns:1.05fr .95fr;gap:48px;align-items:center}
.planner-band h2 em{font-style:normal;color:#7fb0ff}
.planner-list{list-style:none;display:flex;flex-direction:column;gap:16px}
.planner-list li{display:flex;gap:12px;align-items:flex-start}
.planner-list li .tk{color:#7fb0ff;font-weight:800;flex:none;margin-top:1px}
.planner-list li div{display:flex;flex-direction:column;gap:2px}
.planner-list li b{font-size:15px;font-weight:700}
.planner-list li span{font-size:13px;color:rgba(255,255,255,.72);line-height:1.45}
@media(max-width:1040px){.planner-inner{grid-template-columns:1fr;gap:28px;padding:40px 22px}}
/* landing — FAQ accordion */
.faq{max-width:820px;margin:0 auto;display:flex;flex-direction:column;gap:10px}
.faq details{background:var(--card);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.faq summary{list-style:none;cursor:pointer;padding:15px 18px;font-weight:700;font-size:15px;color:var(--navy);display:flex;justify-content:space-between;align-items:center;gap:12px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:'+';font-size:20px;color:var(--muted);font-weight:600;flex:none}
.faq details[open] summary::after{content:'\2013'}
.faq details[open] summary{border-bottom:1px solid var(--line-2)}
.faq .a{padding:14px 18px 18px;color:var(--muted);font-size:14px;line-height:1.6}

/* =====================================================================
   MODAL + TOAST
   ===================================================================== */
.modal-bg{position:fixed;inset:0;background:rgba(15,33,55,.5);backdrop-filter:blur(3px);
  display:none;align-items:center;justify-content:center;z-index:80;
  padding:max(20px,env(safe-area-inset-top,0px)) max(20px,env(safe-area-inset-right,0px))
          max(20px,env(safe-area-inset-bottom,0px)) max(20px,env(safe-area-inset-left,0px))}
.modal-bg.open{display:flex}
.modal{background:#fff;border-radius:var(--r-lg);box-shadow:var(--sh-3);width:100%;max-width:440px;
  padding:24px;animation:pop .18s var(--ease);max-height:calc(100vh - 40px);overflow-y:auto}
/* dvh, not vh: on iOS Safari 100vh is the viewport with the toolbars HIDDEN, so a tall modal put
   its action buttons underneath the browser chrome. Declared after the vh line as a fallback. */
.modal{max-height:calc(100dvh - 40px)}
@keyframes pop{from{transform:translateY(10px) scale(.98);opacity:0}to{transform:none;opacity:1}}
.modal.lg{max-width:660px}/* wider modal for builders with line-item tables (e.g. New invoice) */
.modal h3{font-size:19px;font-weight:800;letter-spacing:-.3px}
.modal .confirm-line{display:flex;justify-content:space-between;padding:10px 0;border-top:1px solid var(--line-2);font-size:13.5px}
.modal .confirm-line:first-of-type{border-top:0}
.modal .confirm-line b{font-weight:700}
.modal-actions{display:flex;gap:10px;margin-top:20px}

.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(20px);
  background:var(--navy);color:#fff;padding:13px 20px;border-radius:var(--r);box-shadow:var(--sh-3);
  font-size:13.5px;font-weight:600;display:flex;align-items:center;gap:10px;opacity:0;pointer-events:none;
  transition:.25s var(--ease);z-index:90}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
.toast .tick{font-weight:800}
.toast.t-success .tick{color:#7fffb0}
.toast.t-error .tick{color:#ff8d8d}
.toast.t-warn .tick{color:#ffd479}
.toast.t-error{box-shadow:inset 3px 0 0 #ff8d8d, var(--sh-2)}
.toast.t-warn{box-shadow:inset 3px 0 0 #ffd479, var(--sh-2)}

/* =====================================================================
   WEEK CALENDAR (shared component — availability / book / view)
   ===================================================================== */
.cal-toolbar{display:flex;align-items:center;gap:10px;margin-bottom:14px;flex-wrap:wrap}
.cal-toolbar .wk-range{font-size:15.5px;font-weight:800;color:var(--navy);min-width:170px}
.cal-toolbar .navbtns{display:flex;gap:6px}
.wk-scroll{max-height:64vh;overflow:auto;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.wk{position:relative;background:#fff}
.wk-grid{display:grid;grid-template-columns:58px repeat(7,1fr);grid-template-rows:44px repeat(28,30px)}
.wk-corner{position:sticky;top:0;background:#fff;z-index:4;border-bottom:1px solid var(--line)}
.wk .dh{position:sticky;top:0;z-index:4;background:#fff;border-bottom:1px solid var(--line);border-left:1px solid var(--line-2);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px}
.wk .dh span{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--faint)}
.wk .dh b{font-size:15px;font-weight:800;color:var(--navy);line-height:1}
.wk .dh.today b{color:var(--brand)}
.wk .dh.today span{color:var(--brand)}
.wk .dh[data-col]{cursor:pointer}
.wk .dh[data-col]:hover b{color:var(--blue)}
.wk .tl{font-size:10.5px;color:var(--faint);text-align:right;padding-right:8px;transform:translateY(-7px);white-space:nowrap}
/* the first label (8:00) would sit under the sticky day-header — drop it just below the line so it reads in full */
.wk .tl.tl-first{transform:translateY(4px)}
.wk .cell{border-left:1px solid var(--line-2);border-top:1px solid var(--line)}
.wk .cell.half{border-top:1px dashed var(--line-2)}
.wk .cell.past{background:var(--bg)}
.wk .cell.toggle{cursor:pointer;transition:background .1s var(--ease)}
.wk .cell.toggle:hover{background:var(--blue-soft)}
.wk .cell.on{background:var(--blue);border-top-color:var(--blue);cursor:pointer;position:relative}
.wk .cell.on:hover{background:#2f6bff}
.wk .cell.open{cursor:pointer;background:#f0fdf4;transition:background .1s var(--ease)}
.wk .cell.open:hover{background:#d7f5e1;box-shadow:inset 0 0 0 1.5px var(--green)}
.wk .cell[data-date]{cursor:pointer}
.wk .cell[data-date]:not(.open):hover{background:var(--blue-soft)}
.wk-events{position:absolute;inset:0;pointer-events:none}
.wk-today-band{position:absolute;background:rgba(192,57,43,.055);pointer-events:none}
.wk .ev{position:absolute;pointer-events:auto;cursor:pointer;margin:1px 3px;padding:3px 7px;border-radius:7px;
  text-align:left;overflow:hidden;font-family:inherit;display:flex;flex-direction:column;gap:1px;
  box-shadow:var(--sh-1);transition:transform .1s var(--ease),box-shadow .1s var(--ease)}
.wk .ev:hover{transform:translateY(-1px);box-shadow:var(--sh-2);z-index:5}
.wk .ev b{font-size:11.5px;font-weight:800;color:var(--navy);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wk .ev .ev-meta{font-size:10px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wk .ev .ev-tag{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;color:var(--brand)}
.cal-legend{display:flex;gap:18px;margin-top:14px;font-size:12px;color:var(--muted);flex-wrap:wrap}
.cal-legend span{display:flex;align-items:center;gap:6px}
.cal-legend i{width:11px;height:11px;border-radius:3px;display:block}
.ev.ev-pending{border-style:dashed!important}

/* calendar tutor filters + view toggle */
.cal-filters{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
.fchip{display:inline-flex;align-items:center;gap:7px;height:30px;padding:0 12px;border-radius:99px;border:1px solid var(--line);background:#fff;font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;transition:.12s var(--ease)}
.fchip .swatch{width:9px;height:9px;border-radius:50%;background:var(--c,var(--blue))}
.fchip.on{border-color:var(--navy);color:var(--navy);background:var(--bg)}
.fchip:hover{border-color:var(--navy)}
.viewseg{display:inline-flex;border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.viewseg button{height:34px;padding:0 14px;border:0;background:#fff;font-size:13px;font-weight:600;color:var(--muted)}
.viewseg button.on{background:var(--navy);color:#fff}
.chip{display:inline-flex;align-items:center;gap:6px;padding:6px 13px;border-radius:99px;border:1px solid var(--line);font-size:12.5px;font-weight:600;cursor:pointer;background:#fff;color:var(--muted)}
.chip.on{background:var(--blue);color:#fff;border-color:var(--blue)}

/* month grid */
.mcal{display:grid;grid-template-columns:repeat(7,1fr);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:#fff}
.mcal .mdow{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);text-align:center;padding:9px 0;border-bottom:1px solid var(--line);border-left:1px solid var(--line-2)}
.mcal .mcell{min-height:104px;border-left:1px solid var(--line-2);border-top:1px solid var(--line-2);padding:5px 6px;cursor:pointer;display:flex;flex-direction:column;gap:3px;transition:background .1s var(--ease)}
.mcal .mcell:hover{background:var(--blue-soft)}
.mcal .mcell.out{background:var(--bg);color:var(--faint)}
.mcal .mcell.today .dn{background:var(--brand);color:#fff;border-radius:50%;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center}
.mcal .dn{font-size:12.5px;font-weight:700;align-self:flex-start}
.mcal .mev{font-size:10.5px;font-weight:600;padding:2px 6px;border-radius:5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mcal .mmore{font-size:10px;color:var(--muted);font-weight:600}

/* phone month: the WHOLE month has to be visible, so a cell is just the date and a dot for
   "has lessons"; the chosen day's lessons are listed underneath. Full event chips need a
   desktop-width cell — at 390px seven of them are unreadable and run off the screen. */
.mcal-sm .mcell{min-height:44px;padding:4px 0;align-items:center;justify-content:flex-start;gap:3px}
.mcal-sm .mdow{padding:8px 0;border-left:0}
.mcal-sm .dn{font-size:13.5px;font-weight:600;align-self:center}
.mcal-sm .mcell.sel{background:var(--blue-soft)}
/* :not(.today) — today is a filled red disc, so recolouring its number to blue put blue text on
   the red circle. Today keeps white-on-red whether or not it is the selected day. */
.mcal-sm .mcell.sel:not(.today) .dn{color:var(--blue);font-weight:800}
.mcal-sm .mdot{width:5px;height:5px;border-radius:50%;background:var(--blue);display:block}
/* the padding cells either side of the month are blank (see buildMonthPhone) — a tinted empty
   cell shows where the month starts and ends without listing another month's dates */
.mcal-sm .mcell.out{cursor:default}
.mcal-sm .mcell.out:hover{background:var(--bg)}
/* A detail row whose value is a LIST, not a value. .kv is label-left / value-right, which
   turns three students into one right-aligned run-on string that wraps mid-name. The label
   takes its own line and the list sits under it as one row per person. */
.kvb{padding:11px 0;border-top:1px solid var(--line-2)}
.kvb:first-child{border-top:0}
.kvb-l{display:block;color:var(--muted);font-size:13.5px;margin-bottom:8px}
.stu-list{display:flex;flex-direction:column;gap:6px}
.stu-row{display:flex;align-items:center;gap:10px;background:var(--bg);
  border:1px solid var(--line-2);border-radius:11px;padding:7px 10px}
.stu-row .avatar.sm{flex:none}
.stu-row b{flex:1;min-width:0;font-size:13.5px;font-weight:700;color:var(--navy);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stu-row .yr{flex:none;font-size:11.5px;font-weight:700;color:var(--muted);background:#fff;
  border:1px solid var(--line);border-radius:999px;padding:3px 9px;white-space:nowrap}

.magenda{margin-top:16px}
.magenda .mah{font-size:13px;font-weight:800;color:var(--navy);margin-bottom:9px}
.magenda .marow{display:flex;align-items:flex-start;gap:11px;width:100%;text-align:left;
  background:#fff;border:1px solid var(--line);border-left:3px solid var(--blue);
  border-radius:11px;padding:11px 13px;margin-bottom:8px;cursor:pointer;font-family:inherit}
.magenda .mat{font-size:12px;font-weight:700;color:var(--muted);flex:none;min-width:66px;padding-top:1px}
.magenda .mam{min-width:0}
.magenda .mam b{display:block;font-size:13.5px;color:var(--navy)}
.magenda .mam span{font-size:12px;color:var(--muted)}

/* data table (CRM contacts) + toolbars */
.toolbar{display:flex;gap:8px;align-items:center;margin-bottom:16px;flex-wrap:wrap}
.btn-icn{display:inline-flex;align-items:center;gap:6px}
.ctable{width:100%;border-collapse:collapse}
.ctable th{text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);font-weight:700;padding:9px 12px;border-bottom:1px solid var(--line);white-space:nowrap;cursor:pointer;user-select:none}
.ctable th:hover{color:var(--muted)}
.ctable td{padding:11px 12px;border-bottom:1px solid var(--line-2);font-size:13px;vertical-align:middle}
.ctable tbody tr:hover td{background:var(--bg)}
.ctable .nm{display:flex;align-items:center;gap:10px;font-weight:700;color:var(--navy)}
.ctable .nm a{color:var(--blue)}
.tagrow{display:flex;gap:5px;flex-wrap:wrap}
.tagpill{font-size:10.5px;font-weight:700;padding:2px 9px;border-radius:99px;background:var(--bg);color:var(--muted)}
.filterbar{display:flex;gap:14px;flex-wrap:wrap;align-items:flex-end;background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:14px;margin-bottom:16px}
.filterbar .field{margin:0;min-width:150px}
.filterbar .field label{font-size:11px}

/* invoice summary buckets */
.buckets{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:20px}
.bucket{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);padding:16px 18px;box-shadow:var(--sh-1)}
.bucket .bk-top{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;color:var(--muted)}
.bucket .bk-amt{font-size:24px;font-weight:800;letter-spacing:-.5px;margin-top:8px;color:var(--navy)}
.bucket .bk-dot{width:9px;height:9px;border-radius:50%}
/* the label sits ABOVE the amount, so a label that wraps to two lines used to push its amount
   down out of line with the card beside it. Bottom-align the amounts instead. */
.bucket{display:flex;flex-direction:column}
.bucket .bk-amt{margin-top:auto;padding-top:8px}
@media(max-width:1040px){.buckets{grid-template-columns:repeat(2,1fr)}}

/* invoices billing bar: the default rate on the left, the Stripe status and the four things you
   can do from here on the right. Lives here rather than inline on the element so the phone
   layout below can restate it without fighting an inline style. */
#billBar{display:flex;gap:16px;align-items:flex-end;flex-wrap:wrap;margin-bottom:14px}

/* row action dropdown menu */
.rowmenu{position:relative;display:inline-block}
.rowmenu .mbtn{border:1px solid var(--line);background:#fff;border-radius:8px;height:30px;padding:0 10px;font-weight:700;color:var(--muted);cursor:pointer}
.rowmenu .mbtn:hover{border-color:var(--navy);color:var(--navy)}
.rowmenu .menu{position:absolute;right:0;top:34px;background:#fff;border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-3);min-width:170px;padding:6px;z-index:30;display:none}
.rowmenu.open .menu{display:block}
.rowmenu .menu button{display:block;width:100%;text-align:left;border:0;background:none;padding:8px 10px;border-radius:8px;font-size:13px;color:var(--ink);cursor:pointer}
.rowmenu .menu button:hover{background:var(--bg)}
.rowmenu .menu button.danger{color:var(--crimson)}
.rowmenu .menu .sep{height:1px;background:var(--line-2);margin:5px 4px}

/* key/value detail rows */
.kv{display:flex;justify-content:space-between;gap:12px;padding:10px 0;border-top:1px solid var(--line-2);font-size:13.5px}
.kv:first-child{border-top:0}.kv span{color:var(--muted)}.kv b{font-weight:700;text-align:right}

/* onboarding pipeline board */
.pipe{display:grid;gap:14px;align-items:start}
.pcol{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-lg);padding:10px}
.pcol .ph{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:700;display:flex;align-items:center;gap:8px;padding:4px 6px 11px}
.pcol .ph .n{background:#fff;border:1px solid var(--line);border-radius:99px;font-size:11px;padding:0 7px}
.pcard{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:11px 12px;margin-bottom:9px;box-shadow:var(--sh-1)}
.pcard:last-child{margin-bottom:0}
.pcard .pc-top{display:flex;align-items:center;gap:9px}
.pcard b{font-size:13px;color:var(--navy)}
.pcard p{font-size:11.5px;color:var(--muted);margin-top:5px}
.pcard .pc-act{display:flex;gap:6px;margin-top:9px}
.pcard .pc-act button{font-size:11px;font-weight:600;border:1px solid var(--line);background:#fff;border-radius:7px;padding:3px 8px;color:var(--muted);cursor:pointer}
.pcard .pc-act button:hover{border-color:var(--blue);color:var(--blue)}
.pcard[draggable=true]{cursor:grab}
.pcard.dragging{opacity:.45;cursor:grabbing}
.pcol.dragover{outline:2px dashed var(--blue);outline-offset:-3px;background:var(--blue-soft)}
.linkbox{display:flex;gap:10px;align-items:center;background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:0 4px 0 14px;height:46px}
/* min-width:0 because an <input> has an intrinsic minimum width from its size attribute, so
   flex:1 alone would not let it shrink — it held the row ~180px wider than the modal and pushed
   the Copy button off the edge. */
.linkbox input{flex:1;min-width:0;border:0;background:transparent;outline:0;font-size:13.5px;color:var(--ink)}

/* multi-select student picklist (booking modal) */
.picklist{display:flex;flex-direction:column;gap:2px;max-height:168px;overflow:auto;border:1px solid var(--line);border-radius:var(--r);padding:6px}
.picklist .pick{display:flex;align-items:center;gap:10px;padding:7px 9px;border-radius:8px;cursor:pointer;font-size:13.5px}
.picklist .pick:hover{background:var(--blue-soft)}
.picklist .pick input{width:16px;height:16px;flex:none;accent-color:var(--blue)}
.picklist .pick em{font-style:normal;color:var(--muted);font-size:12px;margin-left:4px}

/* grouped list section headers (students / contacts) */
.grouphead{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);padding:16px 2px 6px;border-bottom:1px solid var(--line-2);margin-bottom:4px}
.grouphead:first-child{padding-top:2px}
.grouphead span{font-size:11px;font-weight:700;color:var(--muted);background:var(--bg);border-radius:99px;padding:1px 8px}

/* tiny chart legend dot */
.legend-dot{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);margin-left:14px}
.legend-dot::before{content:"";width:10px;height:10px;border-radius:3px;background:var(--c,var(--blue))}

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
.menu-btn{display:none}
@media(max-width:1040px){
  .stats{grid-template-columns:repeat(2,1fr)}
  /* an odd number of tiles leaves the last one alone on its row with an empty half beside it
     (My Pay has three). Let it span the row instead, so the block ends square. */
  .stats > .stat:last-child:nth-child(odd){grid-column:1 / -1}
  .grid-2,.book-grid{grid-template-columns:1fr}
  .slots-panel{position:static}
  .earn-grid{grid-template-columns:1fr!important}
  #ownerCharts{grid-template-columns:1fr!important}
}
@media(max-width:860px){
  :root{--sb-w:0px}
  .sidebar{transform:translateX(-100%);transition:transform .22s var(--ease);width:252px}
  .sidebar.open{transform:none;box-shadow:var(--sh-3)}
  .main{margin-left:0}
  .menu-btn{display:flex}
  .auth{grid-template-columns:1fr}
  .auth-aside{display:none}
  .hero{grid-template-columns:1fr;padding:36px 22px}
  .hero h1{font-size:34px}
  .hero-art{display:none}
  .searchbox{display:none}
  .content{padding:18px 18px calc(28px + env(safe-area-inset-bottom,0px))}
  /* phone topbar: tighter, and everything that can overflow is allowed to truncate */
  .topbar{gap:10px;
    padding:10px calc(14px + env(safe-area-inset-right,0px)) 10px calc(14px + env(safe-area-inset-left,0px))}
  .topbar .pagetitle{font-size:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .topbar .sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .topbar .btn{white-space:nowrap}
}
@media(max-width:560px){
  /* the avatar is enough on a phone; the name+role text is what pushes the bar past the screen */
  .userchip .who{display:none}
  .topbar .sub{display:none}
  /* Pages with two header actions (Calendar, Invoices) can't fit them beside the title, and
     squeezing the title down to "C.." is worse than a second row. Wrap instead: the page name
     always stays readable, and the actions flow underneath at full size. */
  .topbar{flex-wrap:wrap;row-gap:8px}
  .topbar .spacer{flex:1 0 0}
  .topbar .btn{padding:8px 12px;font-size:12.5px}
  /* When the bar wrapped it did so in DOM order, which stranded the account button alone on a
     second row at the far left — on Calendar and Contacts, which carry two actions, and on
     Tutor Opportunities, whose title and single wide action fill the row between them.
     So a page that has header actions gets a deliberate two-row bar: page name and account on
     the first, the actions across the second. Letting it depend on whether things happen to
     fit meant the account button sat in the corner on some pages and mid-row on others; every
     action page looking the same is worth more than the row it costs. Pages with no header
     action are untouched and stay on one row.
     The 14px allowance covers the gap plus the inline margin one of them carries; at 6px the
     pair overflowed by a few pixels and stacked one per row. */
  .topbar > div:not(.spacer){flex:1 1 auto;min-width:96px}
  .topbar:has(.btn) > div:not(.spacer){min-width:55%}
  .topbar:has(.btn) .userchip{order:1}
  .topbar:has(.btn) .btn{order:2;flex:1 1 calc(50% - 14px)}
  /* …except a lone tertiary action, which on these pages is a back link ("← Invoices").
     Stretching that across the row made it the loudest thing on the page, above the title it
     was returning from. A lone PRIMARY action still fills the row: that one is the point.
     order:0 with it, so it stays ahead of the account button in DOM order and the account button
     keeps the corner — reordering it to the end put the avatar in the middle of the row. */
  .topbar:has(.btn):not(:has(.btn + .btn)) .btn-ghost{flex:0 0 auto;order:0}
}
.scrim{display:none;position:fixed;inset:0;background:rgba(15,33,55,.4);z-index:35}
.scrim.open{display:block}

/* Messages back control — hidden on desktop, where the list is always beside the thread */
.thread-back{display:none;align-items:center;justify-content:center;width:36px;height:36px;flex:none;
  margin-right:10px;border:1px solid var(--line);border-radius:10px;background:#fff;
  color:var(--muted);font-size:20px;line-height:1;cursor:pointer;font-family:inherit}
.thread-back:active{background:var(--bg)}

/* ---- touch targets -------------------------------------------------------
   Apple's guidance is a 44pt minimum, and most of the app's controls were 32px
   (.btn-sm) or 13px (bare checkboxes). Scoped to pointer:coarse so the desktop
   UI keeps its density, and expressed as min-* rather than height/width so it
   also wins over the inline heights some pages set on their own controls.
   Calendar slot cells stay 30px on purpose: weekcal positions events off that
   grid, and a full-width row is easy to hit despite the height. */
@media(pointer:coarse){
  .btn,.btn-sm{min-height:44px}
  .btn-sm{padding-left:14px;padding-right:14px}
  .iconbtn{min-width:44px;min-height:44px}
  .userchip{min-height:44px}
  .input,.cselect-btn,.cdate-btn,.ctime-btn,select,textarea{min-height:44px}
  input[type=checkbox],input[type=radio]{min-width:22px;min-height:22px}
  .chip,.lz-chip{min-height:44px}
  .pcard .pc-act button{min-height:44px;padding:6px 12px}
  .mbtn{min-height:44px;min-width:44px}
  /* catch-all for the one-off inline buttons pages define themselves. .modal is listed separately
     because modals are siblings of .content, not inside it, so the original rule reached none of
     them — every one-off control in all 24 modals was missed by the touch-target pass. */
  .content button,.content a.btn,.modal button,.modal a.btn{min-height:44px}
  /* …except genuinely dense controls, where 44px would wreck the layout:
     the rich-text signature toolbar and the date/time picker grids. */
  .sig-tb{min-width:40px;min-height:40px}
  .cpop button,.cpop .cal-day,.cselect-menu *{min-height:0}
}

/* ---- phone tab bar -------------------------------------------------------
   The destinations each role actually reaches for, at the thumb; everything else
   is behind More, which opens the same sidebar. Desktop never sees it. */
.tabbar{display:none}
@media(max-width:700px){
  .tabbar{display:flex;position:fixed;left:0;right:0;bottom:0;
    background:rgba(255,255,255,.94);backdrop-filter:saturate(1.4) blur(10px);
    border-top:1px solid var(--line);z-index:34;
    /* z-index sits BELOW the scrim (35) and the sidebar (40): when the menu is open the tab bar
       must not cover it, or the last nav items and Log out are unreachable. */
    /* The bottom inset is the home-indicator strip (34px on a notched iPhone). Reserving all of
       it parked the icons and labels ~40px above the screen edge with a band of empty white
       under them. Give back 14px: the bar sits where a native tab bar sits, and the buttons
       still stop ~20px clear of the indicator. */
    padding:0 max(4px,env(safe-area-inset-left,0px)) max(6px,calc(env(safe-area-inset-bottom,0px) - 14px)) max(4px,env(safe-area-inset-right,0px))}
  .tabbar a,.tabbar button{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;
    justify-content:center;gap:3px;padding:8px 2px 7px;border:0;background:none;cursor:pointer;
    color:var(--muted);font-family:inherit;font-size:10.5px;font-weight:600;line-height:1.2}
  .tabbar svg{width:22px;height:22px;flex:none}
  .tabbar span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .tabbar a.active{color:var(--blue)}
  .tabbar a:active,.tabbar button:active{background:var(--bg)}
  /* keep content clear of the bar */
  .content{padding-bottom:calc(84px + env(safe-area-inset-bottom,0px))}
  /* More replaces the hamburger, which also frees room in the top bar */
  .menu-btn{display:none}
  /* ---- list rows (students, sessions, logs) ----
     These are desktop rows: avatar | details | progress | two buttons. Squeezed into 390px the
     details column collapses and text wraps mid-phrase ("Maya / Patel", "next / Tue, / 4 / Aug")
     while the buttons spill past the card edge. Let the row wrap into stacked bands instead. */
  /* align-items:flex-start so the avatar sits level with the name it belongs to. Centred against
     a three-line block it floated in the middle of the row with nothing to line up against, which
     is what made a list impossible to scan down. (Rows led by a time are centred instead — see
     below: their time shares a line with the row's action, not with the title.) */
  .session{flex-wrap:wrap;row-gap:10px;align-items:flex-start;padding:16px 4px}
  .session > *{min-width:0}
  /* A row that leads with a TIME OR DATE is a lesson, and on a phone it reads as a stacked block:
     a header line carrying the time and whatever trails the row (status badge, action, tutor
     name), then the title and its meta across the full width underneath. The 58px centred time
     column was taking a third of a 390px line, so every title wrapped mid-phrase, the chips below
     it wrapped again, and the action finished alone on a line with nothing above it to line up
     against — three ragged left edges in one row. Now everything starts at the same edge.
     .when grows to fill the header line, which is what parks the trailing items hard right
     (flex-grow resolves before auto margins, so it also beats the margin-left:auto rules below).
     Rows that lead with an AVATAR (team, my students) are a different shape and keep the
     side-by-side layout they already had. */
  .session:has(> .when){align-items:center}
  .session > .when{flex:1 1 auto;width:auto;text-align:left;display:flex;align-items:baseline;gap:6px}
  .session:has(> .when) > .meta{order:2;flex:1 1 100%!important}
  .session:has(> .when) > .row,.session:has(> .when) > div:has(.bar){order:3}
  /* !important because these carry an inline flex:1, i.e. flex-basis:0, so without it the meta
     column collapses to ~44px and its text renders one character per line (lessons, team,
     lesson-logs all hit this). */
  .session .meta{flex:1 1 60%!important;min-width:0}
  /* Two lines, then ellipsis. These titles are "student · topic", so truncating at one line on a
     phone reliably cut the topic — the useful half — leaving "Ava Thompson · Chemical Equili…". */
  .session .meta h4{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
    overflow:hidden;white-space:normal;overflow-wrap:break-word}
  /* An action that wraps onto its own line sits bottom-right, where a card action belongs,
     rather than floating at the left margin unattached to anything. Where a status badge shares
     that line this also separates them: status left, action right. !important because some of
     these buttons carry an inline margin-left, which would otherwise win. */
  .session > .btn:last-child{margin-left:auto!important}
  /* same for a trailing caption block — the student's upcoming sessions end with the tutor's
     name, which wrapped to its own line and sat at the far left under the date column, reading
     as a stray rather than as the row's attribution */
  .session > :last-child:not(.meta):not(.when):not(.row):not(.btn){margin-left:auto}
  .session .meta p{display:flex;flex-wrap:wrap;gap:4px 10px}
  .session .meta p .i{white-space:nowrap}
  .session > div:has(.bar){flex:1 1 100%;width:auto!important}   /* the progress block */
  .session > .row{flex:1 1 100%;margin-left:0!important}
  /* Button groups line up 2-up instead of each sizing to its own label, which is what made
     "Stripe: connected / Pricing settings / Generate this week" look like mismatched boxes.
     But equal widths are only right for a TOOLBAR — a row that is nothing but buttons. In a
     "text + one action" row the same rule hands the action half the screen and squeezes the
     copy into a vertical sliver: "Chase / Marcus / Lee's / WWCC" beside a wide empty Add.
     :has() lets the rule ask which kind of row this actually is. */
  .content .row{flex-wrap:wrap}
  .content .row:not(:has(> :not(.btn):not(.spacer))) > .btn{flex:1 1 calc(50% - 6px)}
  /* Three or more buttons in a row is one of two things, and they want opposite treatment.
     A FILTER STRIP (the parent's children, the tutor's subjects) should scroll sideways as
     chips — the treatment the settings nav already gets. Halves were wrong for it: "All" and
     one child sat on one row and the second child was left alone on the next at double width.
     An ACTION ROW (Email / Message / Invite / Book a lesson) should wrap, because scrolling
     would leave its most important action half off the edge of the card.
     The discriminator is the primary button: an action row has one, a filter strip doesn't.
     !important on nowrap because the filter rows set flex-wrap:wrap inline. */
  .content .row:not(:has(> :not(.btn):not(.spacer))):has(> .btn:nth-child(3)):not(:has(> .btn-primary)){
    flex-wrap:nowrap!important;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px}
  .content .row:not(:has(> :not(.btn):not(.spacer))):has(> .btn:nth-child(3)):not(:has(> .btn-primary))::-webkit-scrollbar{height:0}
  .content .row:not(:has(> :not(.btn):not(.spacer))):has(> .btn:nth-child(3)):not(:has(> .btn-primary)) > .btn{flex:0 0 auto}
  /* Mixed row: the copy keeps the line and the action stays its natural size. The copy blocks
     carry an inline flex:1, i.e. flex-basis:0, which beats a plain rule, hence !important —
     and it is [style], not div[style], because several of these are spans. 60% is a real wrap
     threshold: the action rides along when there is room and drops below when there isn't. */
  .content .row:has(> :not(.btn):not(.spacer)) > .btn{flex:0 0 auto}
  /* and when it does drop below, it sits at the right edge rather than at the left margin,
     where it reads as leftover rather than as the row's action */
  .content .row:has(> :not(.btn):not(.spacer)) > .btn:last-child{margin-left:auto}
  .content .row > [style*="flex:1"]{flex:1 1 60%!important;min-width:0}
  .content .row > .spacer{display:none}
  /* A compose row is field + submit. .input is width:100%, which as a flex item claims the whole
     line and drops the button below it, orphaned at the left margin. Let it share the line the
     way it already does on desktop. */
  .content .row > .input{flex:1 1 120px;width:auto;min-width:0}
  /* Card headers are title + action. The action sits beside the title when it fits and wraps
     below at its own size when it doesn't. Letting it grow instead turned every "Dismiss" and
     "Open the board" into a full-width bar louder than the card it belonged to.
     Sizing the title from its own content (rather than a fixed share) is what makes the choice
     automatic: flex wraps a line before it shrinks anything on it, so a short title keeps its
     action alongside and a long one pushes the action down without ever being squeezed itself. */
  .section-h{flex-wrap:wrap;gap:8px;row-gap:9px}
  .section-h h2{flex:1 1 auto;min-width:0}
  .section-h > .btn,.section-h > a.btn{flex:0 0 auto;max-width:100%}
  .section-h > .btn:last-child,.section-h > a.btn:last-child{margin-left:auto}

  /* ---- the invoices billing bar ----
     Four buttons wrapping at their own label widths is what made this cluster read as a pile of
     mismatched boxes: "Pricing settings" wide, "Invoice settings" narrower, the Stripe chip
     narrower still, and no two edges lining up. It is a flex bar rather than a .row, so none of
     the toolbar rules above ever reached it. On a phone it becomes a two-column grid — every
     button is exactly half the card and every edge lines up. The rate field and the Stripe chip
     take a line each because they aren't actions; Connect Stripe and Generate this week take the
     full width because they're the two that carry weight (and it keeps the grid even whether or
     not Stripe is connected, since Connect Stripe hides itself once it is). */
  #billBar{display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:center}
  #billBar > .field,#billBar > #stripeChip,#billBar > #connectStripe,#billBar > .btn-primary{grid-column:1/-1}
  #billBar > #stripeChip{justify-self:start}
  #billBar > .spacer{display:none}
  #billBar > .btn{width:100%;margin:0}

  /* Multi-column layouts stack on a phone. !important because .pipe's columns are set inline
     by onboarding.html and these page grids are declared after app.css. A 5-column kanban or a
     200px label column can't shrink below its content, which expands the layout viewport and
     makes iOS zoom the whole page out. */
  /* minmax(0,1fr), not 1fr: a bare 1fr means minmax(auto,1fr), so the column can still never be
     narrower than its content and the viewport blows out anyway. This is the same trap that made
     the onboarding board 1060px wide. */
  .pipe{grid-template-columns:minmax(0,1fr)!important}
  .set-grid,.pl-grid{grid-template-columns:minmax(0,1fr)!important}
  /* .pb-grid is the manual Plan Builder's editor + live preview. It had no phone rule at all, so
     the preview column sat half off the right edge of every screenshot of that page. Its preview
     is also position:sticky, which in a stacked layout floats over the fields — the same trap the
     settings nav hit in 205. .map-grid (Import Data) stacks at 640px, which leaves 640-700 broken. */
  .pb-grid,.map-grid{grid-template-columns:minmax(0,1fr)!important}
  .pb-preview{position:static!important}
  /* a phone has the vertical room a desktop grid doesn't, so give typed fields more of it */
  textarea.input{min-height:calc(1.5em * 6 + 26px)}   /* 24px padding + 2px border, box-sizing:border-box */
  /* Settings' side nav is position:sticky. Once the grid stacks it stops being a column and
     just floats over the cards, so every label landed on top of a row. Turn it into a
     horizontal strip of chips at the top instead. */
  .set-nav{position:static!important;flex-direction:row!important;overflow-x:auto;
    gap:6px;padding-bottom:8px;margin-bottom:6px;border-bottom:1px solid var(--line-2);
    -webkit-overflow-scrolling:touch}
  .set-nav::-webkit-scrollbar{height:0}
  .set-nav a{white-space:nowrap;flex:none;border:1px solid var(--line);border-radius:99px}
  /* Messages is a 300px list + 1fr thread, which left the thread about 40px wide at 390px.
     On a phone the two share the screen instead: the list fills it, opening a conversation
     replaces it with the thread, and the back control returns. */
  .chat{grid-template-columns:minmax(0,1fr)!important;height:auto!important;min-height:66vh}
  .chat > .thread{display:none}
  .chat.on-thread > .convo-list{display:none}
  .chat.on-thread > .thread{display:flex;flex-direction:column;min-height:66vh}
  .thread-back{display:inline-flex}
  /* Table columns squeezed into 390px wrap mid-phrase. Give them a readable floor and let the
     wrapper scroll sideways, which it already supports. */
  .ctable{min-width:720px}
  /* …except the two lists that stop being tables on a phone (see invoices.html for the other).
     Contacts as a two-column table wrapped every second name onto a second line and still had
     nowhere to put the phone or email. As a card it holds all of it comfortably: who they are,
     what they are, and both ways to reach them. */
  .ctable.inv-table,.ctable.con-table{min-width:0}
  /* same as invoices: the rows are the cards, so the panel round them is a second border.
     Both pages use #listCard for the panel that holds a toolbar above a list. */
  #listCard{background:none;border:0;box-shadow:none;padding:0}
  #listCard .toolbar,#listCard .op-filters{background:var(--card);border:1px solid var(--line);
    border-radius:var(--r-lg);padding:14px;margin-bottom:14px}
  .con-table,.con-table tbody{display:block}
  .con-table thead{display:none}
  .con-table tr{display:grid;grid-template-columns:1fr auto;gap:2px 10px;
    border:1px solid var(--line);border-radius:14px;background:#fff;padding:13px 14px;margin-bottom:10px}
  .con-table td{display:block;border:0;padding:0;white-space:normal!important}
  .con-table td:nth-child(1){grid-area:1/1/auto/-1;font-size:15px}          /* avatar + name  */
  .con-table td:nth-child(6){grid-area:2/1/auto/-1;margin-top:4px}          /* tags           */
  .con-table td:nth-child(4){grid-area:3/1/auto/-1;margin-top:8px}          /* their students */
  .con-table td:nth-child(2){grid-area:4/1;font-size:13px;margin-top:6px}   /* phone          */
  .con-table td:nth-child(5){grid-area:4/2;font-size:12px;margin-top:6px;justify-self:end}
  .con-table td:nth-child(3){grid-area:5/1/auto/-1;font-size:13px;overflow-wrap:anywhere}
  /* the children read as a bare list of names once the column heading is gone, so the card
     labels them; a contact with none (a tutor) drops the line rather than saying "Students —" */
  .con-table td.con-students::before{content:'Students';display:block;font-size:10.5px;
    text-transform:uppercase;letter-spacing:.5px;color:var(--faint);font-weight:700;margin-bottom:4px}
  .con-table td.con-students.empty{display:none}
  /* The opportunity board used to get the same floor, but it has ten columns: any width that
     fits them all still left the wordy ones a couple of characters wide. It now drops to its
     four identifying columns on a phone (see opportunities.html) and needs no floor at all. */
  .formrow{grid-template-columns:minmax(0,1fr)}   /* paired fields stack rather than squeeze */
  /* Two full-label actions ("Onboard a new student →" + "Save assignments") don't fit side by
     side in a 350px modal, and without wrapping they ran off its right edge. flex:1 1 auto breaks
     the line before either is squeezed, then each fills the row it lands on. Phone-only: a 660px
     desktop modal fits both, and wrapping there would restack every .btn-block pair. */
  .modal-actions{flex-wrap:wrap}
  .modal-actions > .btn{flex:1 1 auto}
  /* A link plus two actions can't share a 300px line and still show any of the link. The URL
     takes the first row and the actions sit under it, which also lets both be full-size taps. */
  .linkbox{flex-wrap:wrap;height:auto;padding:7px 7px 7px 12px;row-gap:7px}
  .linkbox input{flex:1 1 100%}
  .linkbox .btn{flex:1 1 calc(50% - 5px)}
}

/* cancel/reschedule notification banner (dashboards) */
.notif-banner{border:1px solid var(--line);border-left:3px solid var(--blue);background:#fff;
  border-radius:14px;padding:13px 16px;margin-bottom:18px;box-shadow:var(--sh-1)}
.notif-banner .nb-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px;font-size:14px}
.notif-banner .nb-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.notif-banner .nb-list li{font-size:13px;color:var(--muted);display:flex;align-items:center;gap:9px}
.notif-banner .nb-dot{width:7px;height:7px;border-radius:50%;flex:none}
.notif-banner .nb-cancelled{background:#ef4444}
.notif-banner .nb-rescheduled{background:#f59e0b}
.notif-banner .nb-booked{background:#16a34a}
.notif-banner .nb-running_late{background:#ea580c}
.notif-banner .nb-onboarding_done{background:#16a34a}
.notif-banner .nb-contract_signed{background:#1d4ed8}
.notif-banner .nb-lesson_log_due{background:#f59e0b}
.notif-banner .nb-lesson_log_overdue{background:#ef4444}
.notif-banner .nb-student_note{background:#8b5cf6}
.notif-banner .nb-duration_logged{background:#0ea5e9}

/* session photos (lesson log v2) — private thumbnails in the log modal + the owner gallery */
.lz-photos{display:flex;flex-wrap:wrap;gap:8px}
.lz-photo{position:relative;width:72px;height:72px;border-radius:9px;overflow:hidden;border:1px solid var(--line);background:#f4f6fa;flex:none}
.lz-photo img{width:100%;height:100%;object-fit:cover;display:block}
.lz-photo.is-broken::after{content:'⚠';position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--muted);font-size:18px}
.lz-photo-x{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;border:0;background:rgba(15,33,55,.72);color:#fff;font-size:14px;line-height:1;cursor:pointer;padding:0}
.lz-photo-x:hover{background:#dc2626}
.lz-consent{color:#92400e}
/* lesson-log per-student attendance editor (1 block for 1:1, N for group/centre) */
.lz-stu{border:1px solid var(--line-2);border-radius:10px;padding:11px 12px 12px;margin-bottom:9px}
.lz-stu:last-of-type{margin-bottom:0}
.lz-stu-name{font-size:12.5px;font-weight:700;color:var(--navy);margin-bottom:6px}
.lz-stunote{margin-top:7px}
.lz-att{display:inline-flex;align-items:center;font-size:11px;font-weight:700;padding:3px 9px;border-radius:99px;line-height:1}
.lz-att.Present{background:#ecfdf5;color:#16a34a}
.lz-att.Late{background:var(--amber-soft);color:var(--amber)}
.lz-att.Absent{background:#fef2f2;color:#dc2626}
.lz-att.Mixed{background:var(--amber-soft);color:var(--amber)}
/* family-facing lesson recap cards (parent + student portals) */
.recap{border:1px solid var(--line-2);border-radius:12px;padding:13px 15px;margin-bottom:11px;background:#fff}
.recap:last-child{margin-bottom:0}
.recap-h{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.recap-stu{color:var(--muted);font-size:12.5px;font-weight:600;margin-left:7px}
.recap-date{color:var(--faint);font-size:12px;white-space:nowrap}
.recap-meta{display:flex;align-items:center;gap:8px;margin-top:7px;font-size:12px;color:var(--muted)}
.recap-msg{margin:9px 0 8px;font-size:13.5px;line-height:1.55;color:var(--navy)}
.recap-kv{font-size:12.5px;color:var(--muted);margin-top:3px}
.recap-kv span{font-weight:700;color:var(--navy);margin-right:6px}
/* guided recap composer (lesson-log modal) */
.rc-fields{display:flex;flex-direction:column;gap:7px}
.rc-preview{margin-top:12px;background:var(--blue-soft);border:1px solid #dbe6fb;border-radius:10px;padding:10px 12px}
.rc-preview-head{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.rc-tag{display:block;font-size:9.5px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:var(--blue);margin-bottom:4px}
.rc-preview-head .rc-tag{margin-bottom:0}
/* the lesson-log modal packs a lot in — keep it compact so it fits without scrolling on a laptop */
#logModal .modal{padding:20px}
#logModal .field{margin-bottom:11px}
#logModal .lz-stunote{min-height:50px}
.rc-preview-text{display:block;font-size:13px;line-height:1.55;color:var(--navy)}
.rc-preview-text.empty{color:var(--muted);font-style:italic}
.rc-summary{display:block;width:100%;border:0;background:transparent;outline:0;resize:vertical;font-family:inherit;font-size:13px;line-height:1.55;color:var(--navy);min-height:46px;padding:0}
.rc-summary::placeholder{color:var(--muted);font-style:italic}

/* ============================================================
   LANDING v3 — warm editorial "paper" + app navy (scoped to body.lp)
   ============================================================ */
body.lp{
  --lp-bg:#FBF6EC;--lp-bg-2:#F4ECDB;--lp-surface:#ffffff;--lp-surface-2:#FBF7EF;
  --lp-line:#EBE1CE;--lp-line-2:#DCD0B6;
  --lp-navy:#0f2137;--lp-navy-600:#1e3a5f;
  --lp-ink:#0f2137;--lp-text:#4a443c;--lp-muted:#71695e;
  --lp-brand:#C0392B;--lp-brand-600:#a93226;--lp-brand-2:#e5484d;
  --lp-amber:#bd6a1a;--lp-amber-soft:#fbeede;
  --lp-serif:'Fraunces',Georgia,'Times New Roman',serif;
  background:var(--lp-bg);color:var(--lp-text);-webkit-font-smoothing:antialiased}
body.lp ::selection{background:rgba(192,57,43,.18);color:var(--lp-navy)}
body.lp .lp-nav{position:sticky;top:0;z-index:50;background:rgba(251,246,236,.82);backdrop-filter:saturate(150%) blur(12px);border-bottom:1px solid var(--lp-line)}
body.lp .lp-nav-inner{max-width:1180px;margin:0 auto;padding:13px 28px;display:flex;align-items:center;gap:6px}
body.lp .lp-nav .logo{color:var(--lp-navy);font-weight:800;font-size:21px;letter-spacing:-.4px}
body.lp .lp-nav .logo .dot{color:var(--lp-brand-2)}
body.lp .logo-stack .logo-ed{color:var(--lp-muted)}
body.lp .navlink{color:var(--lp-muted);font-size:13.5px;font-weight:600;padding:8px 12px;border-radius:8px}
body.lp .navlink:hover{color:var(--lp-navy)}
body.lp .spacer{flex:1}
body.lp .btn-glass{background:#fff;color:var(--lp-navy);border:1px solid var(--lp-line-2)}
body.lp .btn-glass:hover{background:var(--lp-bg);border-color:#cdbf9f}
body.lp .btn-primary{background:var(--lp-brand);color:#fff;box-shadow:0 12px 28px -14px rgba(192,57,43,.6)}
body.lp .btn-primary:hover{background:var(--lp-brand-600)}
body.lp .lp-hero{position:relative;max-width:1100px;margin:0 auto;padding:76px 28px 40px;text-align:center;overflow:hidden}
body.lp .lp-hero-glow{position:absolute;left:50%;top:-220px;width:980px;height:560px;transform:translateX(-50%);background:radial-gradient(closest-side,rgba(189,106,26,.12),transparent 70%),radial-gradient(closest-side at 68% 30%,rgba(192,57,43,.08),transparent 66%);z-index:0;pointer-events:none}
body.lp .lp-hero-copy{position:relative;z-index:1;max-width:780px;margin:0 auto}
body.lp .lp-eyebrow{display:inline-flex;align-items:center;gap:8px;background:#fff;border:1px solid var(--lp-line-2);color:var(--lp-navy);font-size:12.5px;font-weight:600;padding:6px 13px;border-radius:99px}
body.lp .lp-eyebrow .dotmark{width:7px;height:7px;border-radius:50%;background:var(--lp-brand-2)}
body.lp .lp-eyebrow-sub{margin-top:18px}
body.lp .lp-hero h1{font-family:var(--lp-serif);font-size:60px;line-height:1.05;letter-spacing:-1px;font-weight:600;margin:20px 0 0;color:var(--lp-navy)}
body.lp .lp-hero h1 em{font-style:italic;color:var(--lp-brand);font-weight:600}
body.lp .lp-lede{font-size:18px;line-height:1.62;color:var(--lp-text);max-width:610px;margin:20px auto 0;text-wrap:balance}
body.lp .lp-cta{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:28px}
body.lp .lp-microproof{margin-top:18px;font-size:12px;color:var(--lp-muted)}
body.lp .lp-hero-shot{position:relative;z-index:1;max-width:980px;margin:46px auto 0}
body.lp .browser{border:1px solid var(--lp-line-2);border-radius:14px;overflow:hidden;background:#fff;box-shadow:0 40px 90px -45px rgba(15,33,55,.4),0 2px 6px rgba(15,33,55,.06)}
body.lp .browser-bar{display:flex;align-items:center;gap:7px;padding:11px 14px;background:var(--lp-bg-2);border-bottom:1px solid var(--lp-line)}
body.lp .browser-bar i{width:11px;height:11px;border-radius:50%;background:#d8cbb0}
body.lp .browser-url{margin-left:12px;font-size:11.5px;color:var(--lp-muted);background:#fff;padding:4px 12px;border-radius:7px;border:1px solid var(--lp-line)}
body.lp .browser img{display:block;width:100%;height:auto}
body.lp .browser img.shot-tall{max-height:460px;object-fit:cover;object-position:top}
body.lp .lp-sec{padding:72px 0}
body.lp .lp-sec-accent{background:var(--lp-bg-2);border-top:1px solid var(--lp-line);border-bottom:1px solid var(--lp-line)}
body.lp .lp-sec-dark{background:var(--lp-navy);border-top:1px solid var(--lp-navy-600);border-bottom:1px solid var(--lp-navy-600);color:#eaf0f7}
/* preview tours: cross-fading tabs in a fixed 16:10 browser frame */
body.lp .tour-frames{position:relative;width:100%;padding-bottom:62.5%;overflow:hidden;font-size:0}
body.lp .tour-frame{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity 1.15s cubic-bezier(.4,0,.2,1)}
body.lp .tour-frame.on{opacity:1;z-index:2}
body.lp img.tour-frame{object-fit:cover;object-position:50% 0%}
body.lp .browser-url b{color:var(--lp-navy);font-weight:700}
/* showcase calendar: slow scroll through every timeslot + a subtle tap */
body.lp .tour-frame.cal{overflow:hidden}
body.lp .cal-shell{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:top}
body.lp .cal-window{position:absolute;left:20.76%;top:29.59%;width:75.97%;height:59.11%;overflow:hidden}
body.lp .cal-window .cal-body{position:absolute;left:0;top:0;width:100%;height:auto;transform:translateY(-33.12%)}
body.lp .tour-frame.cal.on .cal-body{animation:calBodyScroll 6.5s ease-in-out forwards}
@keyframes calBodyScroll{0%,9%{transform:translateY(-5.54%)}88%,100%{transform:translateY(-33.12%)}}
/* contact form status note sits on the WHITE form card, so keep it dark and readable */
body.lp .contact-form .cf-note{color:var(--lp-muted);font-size:13px;margin:2px 0 0}
body.lp .contact-form .cf-note:empty{display:none}
body.lp .contact-form .cf-note a{color:var(--lp-brand);font-weight:700;text-decoration:underline}
/* contact form: "reach us directly" chips (call + email) */
body.lp .cf-reach{margin-top:16px;padding-top:16px;border-top:1px solid var(--lp-line);text-align:center}
body.lp .cf-reach-lead{display:block;font-size:12.5px;font-weight:600;color:var(--lp-muted);margin-bottom:11px}
body.lp .cf-reach-items{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
body.lp .cf-chip{display:inline-flex;align-items:center;gap:8px;padding:9px 15px;border-radius:999px;
  background:var(--lp-navy);color:#fff;font-weight:600;font-size:13.5px;line-height:1;text-decoration:none;
  transition:background .18s,transform .18s,box-shadow .18s}
body.lp .cf-chip:hover{background:var(--lp-navy-600);transform:translateY(-1px);box-shadow:0 12px 24px -14px rgba(15,33,55,.55)}
body.lp .cf-chip svg{opacity:.8}
/* guided reach-out popup: tel:/mailto: are dead ends on desktop, so guide instead of going nowhere */
body.lp .reach{position:fixed;inset:0;z-index:120;display:flex;align-items:center;justify-content:center;padding:20px}
body.lp .reach[hidden]{display:none}
body.lp .reach-backdrop{position:absolute;inset:0;background:rgba(15,33,55,.55);backdrop-filter:blur(3px);animation:reachFade .18s ease}
body.lp .reach-card{position:relative;width:100%;max-width:420px;background:#fff;border:1px solid var(--lp-line);border-radius:18px;
  padding:30px 28px 24px;text-align:center;box-shadow:0 40px 90px -30px rgba(15,33,55,.5);animation:reachPop .22s cubic-bezier(.2,.8,.3,1)}
body.lp .reach-x{position:absolute;top:11px;right:13px;border:0;background:transparent;color:var(--lp-muted);font-size:21px;
  line-height:1;cursor:pointer;padding:4px 7px;border-radius:8px}
body.lp .reach-x:hover{color:var(--lp-navy);background:var(--lp-bg)}
body.lp .reach-ic{display:inline-flex;align-items:center;justify-content:center;width:46px;height:46px;border-radius:14px;
  background:var(--brand-soft);color:var(--lp-brand);margin-bottom:13px}
body.lp .reach-card h3{font-family:var(--lp-serif);font-size:23px;font-weight:600;color:var(--lp-navy);margin:0 0 7px;letter-spacing:-.2px}
body.lp .reach-sub{font-size:13.5px;color:var(--lp-text);line-height:1.55;margin:0 auto 15px;max-width:34ch}
body.lp .reach-sub:empty{display:none}
body.lp .reach-value{font-size:18px;font-weight:700;color:var(--lp-navy);background:var(--lp-bg);border:1px solid var(--lp-line);
  border-radius:12px;padding:13px 14px;margin-bottom:15px;word-break:break-word;user-select:all}
body.lp .reach-actions{display:flex;gap:10px}
body.lp .reach-actions .btn{flex:1;justify-content:center;white-space:nowrap}
body.lp .reach-fallback{margin:13px 0 0;font-size:12.5px;line-height:1.5;color:var(--lp-navy);background:var(--lp-bg);
  border:1px solid var(--lp-line-2);border-radius:10px;padding:10px 12px;text-align:left}
body.lp .reach-fallback[hidden]{display:none}
body.lp .reach-alt{font-size:12.5px;color:var(--lp-muted);line-height:1.55;margin:15px 0 0}
body.lp .reach-alt a{color:var(--lp-brand);font-weight:700}
@keyframes reachFade{from{opacity:0}to{opacity:1}}
@keyframes reachPop{from{opacity:0;transform:translateY(10px) scale(.97)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){body.lp .reach-backdrop,body.lp .reach-card{animation:none}}
@media(max-width:430px){body.lp .reach-actions{flex-direction:column}}
@media(prefers-reduced-motion:reduce){body.lp .tour-frame{transition:none}body.lp .tour-frame.cal.on .cal-body{animation:none;transform:translateY(-5.54%)}}
body.lp .lp-inner{max-width:1180px;margin:0 auto;padding:0 28px}
body.lp .lp-inner-narrow{max-width:820px}
body.lp .lp-sec-head{max-width:660px;margin-bottom:34px}
body.lp .lp-sec-head h2{font-family:var(--lp-serif);font-size:37px;letter-spacing:-.5px;font-weight:600;color:var(--lp-navy);margin:0 0 10px}
body.lp .lp-sec-head p{color:var(--lp-text);font-size:16px;line-height:1.6;margin:0}
body.lp .lp-sec-dark .lp-sec-head h2{color:#fff}
body.lp .lp-sec-dark .lp-sec-head p{color:rgba(234,240,247,.78)}
body.lp .lp-cards{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
body.lp .lp-card{background:var(--lp-surface);border:1px solid var(--lp-line);border-radius:16px;padding:24px;transition:.18s;box-shadow:0 1px 2px rgba(15,33,55,.04)}
body.lp .lp-card:hover{border-color:var(--lp-line-2);transform:translateY(-2px);box-shadow:0 18px 40px -24px rgba(15,33,55,.28)}
body.lp .lp-card .ic{width:42px;height:42px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:19px;margin-bottom:14px}
body.lp .lp-card .ic-indigo{background:var(--lp-amber-soft);color:var(--lp-amber)}
body.lp .lp-card .ic-blue{background:#e9eef6;color:var(--lp-navy)}
body.lp .lp-card .ic-green{background:#e8f5ec;color:#15803d}
body.lp .lp-card .ic-amber{background:var(--brand-soft);color:var(--lp-brand)}
body.lp .lp-card h3{font-size:17px;font-weight:750;color:var(--lp-navy);margin:0 0 6px}
body.lp .lp-card p{font-size:14px;line-height:1.6;color:var(--lp-text);margin:0}
body.lp .lp-split{display:grid;grid-template-columns:0.7fr 1.3fr;gap:48px;align-items:center}
body.lp .lp-split-copy h2{font-family:var(--lp-serif);font-size:34px;letter-spacing:-.5px;font-weight:600;color:var(--lp-navy);margin:14px 0 12px}
body.lp .lp-split-copy h2 em{font-style:italic;color:var(--lp-brand)}
body.lp .lp-split-copy p{font-size:15.5px;line-height:1.65;color:var(--lp-text);margin:0}
body.lp .lp-sec-dark .lp-split-copy h2{color:#fff}
body.lp .lp-sec-dark .lp-split-copy h2 em{color:#ffae8c}
body.lp .lp-sec-dark .lp-split-copy p{color:rgba(234,240,247,.82)}
body.lp .lp-badge{display:inline-block;background:var(--brand-soft);border:1px solid rgba(192,57,43,.25);color:var(--lp-brand);font-size:11.5px;font-weight:700;letter-spacing:.4px;padding:5px 12px;border-radius:99px;text-transform:uppercase}
body.lp .lp-sec-dark .lp-badge,body.lp .contact-band .lp-badge{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.22);color:#ffd9a8}
body.lp .lp-ticks{list-style:none;padding:0;margin:18px 0 0;display:flex;flex-direction:column;gap:10px}
body.lp .lp-ticks li{display:flex;gap:10px;align-items:flex-start;font-size:14.5px;color:var(--lp-text)}
body.lp .lp-sec-dark .lp-ticks li{color:rgba(234,240,247,.88)}
body.lp .lp-ticks .tk{color:#1a9d5c;font-weight:800;flex:none}
body.lp .lp-sec-dark .lp-ticks .tk{color:#54d999}
body.lp .plan-viewer{position:relative;background:#16304d;border:1px solid var(--lp-navy-600);border-radius:14px;box-shadow:0 40px 90px -45px rgba(0,0,0,.55)}
body.lp .plan-viewer-scroll{height:600px;overflow-y:auto;padding:16px;scroll-behavior:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.45) rgba(255,255,255,.08)}
body.lp .plan-viewer-track{display:flex;flex-direction:column;gap:14px}
body.lp .plan-viewer-scroll img{width:100%;height:auto;border-radius:6px;box-shadow:0 12px 30px -16px rgba(0,0,0,.5)}
body.lp .plan-viewer-scroll::-webkit-scrollbar{width:10px}
body.lp .plan-viewer-scroll::-webkit-scrollbar-track{background:rgba(255,255,255,.06);border-radius:99px}
body.lp .plan-viewer-scroll::-webkit-scrollbar-thumb{background:rgba(255,255,255,.45);border-radius:99px;border:3px solid #16304d}
body.lp .plan-viewer-scroll::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.65)}
body.lp .plan-viewer-hint{position:absolute;bottom:0;left:0;right:0;padding:14px;text-align:center;font-size:12px;font-weight:600;color:rgba(234,240,247,.72);background:linear-gradient(transparent,#16304d 65%);pointer-events:none}
body.lp .lp-steps{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
body.lp .lp-step{background:var(--lp-surface);border:1px solid var(--lp-line);border-radius:16px;padding:24px;transition:.18s;box-shadow:0 1px 2px rgba(15,33,55,.04)}
body.lp .lp-step:hover{transform:translateY(-3px);border-color:var(--lp-line-2);box-shadow:0 18px 40px -24px rgba(15,33,55,.28)}
body.lp .lp-step-n{width:40px;height:40px;border-radius:12px;color:#fff;font-weight:800;font-size:17px;display:flex;align-items:center;justify-content:center;margin-bottom:14px}
body.lp .lp-steps>.lp-step:nth-child(1) .lp-step-n{background:var(--lp-navy)}
body.lp .lp-steps>.lp-step:nth-child(2) .lp-step-n{background:var(--lp-brand)}
body.lp .lp-steps>.lp-step:nth-child(3) .lp-step-n{background:var(--lp-amber)}
body.lp .lp-steps>.lp-step:nth-child(4) .lp-step-n{background:#1a9d5c}
body.lp .lp-step h3{font-size:16px;font-weight:750;color:var(--lp-navy);margin:0 0 6px}
body.lp .lp-step p{font-size:13.5px;line-height:1.6;color:var(--lp-text);margin:0}
body.lp .lp-faq details{background:var(--lp-surface);border:1px solid var(--lp-line);border-radius:12px;margin-bottom:10px;padding:2px 18px;box-shadow:0 1px 2px rgba(15,33,55,.04)}
body.lp .lp-faq summary{color:var(--lp-navy);font-weight:600;padding:16px 0}
body.lp .lp-faq .a{color:var(--lp-text)}
body.lp .lp-foot{background:var(--lp-navy);border-top:1px solid var(--lp-navy-600);padding:26px 0;color:rgba(234,240,247,.7);font-size:12.5px}
body.lp .lp-foot .logo{color:#fff}
body.lp .lp-foot .logo .dot{color:var(--lp-brand-2)}
body.lp .lp-foot .logo-ed{color:rgba(255,255,255,.55)}
body.lp .lp-foot .navlink{color:rgba(234,240,247,.7)}
body.lp .lp-foot .navlink:hover{color:#fff}
@media(max-width:840px){
  body.lp .lp-hero{padding-top:52px}
  body.lp .lp-hero h1{font-size:40px;letter-spacing:-.6px}
  body.lp .lp-split{grid-template-columns:1fr;gap:28px}
  body.lp .lp-cards{grid-template-columns:1fr}
  body.lp .lp-steps{grid-template-columns:1fr 1fr}
  body.lp .lp-nav .navlink{display:none}
}
/* social-proof strip */
body.lp .lp-proof{border-top:1px solid var(--lp-line);border-bottom:1px solid var(--lp-line);background:var(--lp-surface)}
body.lp .lp-proof-inner{max-width:1180px;margin:0 auto;padding:20px 28px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:14px 22px}
body.lp .lp-proof-item{display:flex;align-items:center;gap:11px;color:var(--lp-navy);font-size:13.5px;font-weight:600;line-height:1.35;white-space:nowrap}
body.lp .lp-proof-item .pic{width:34px;height:34px;border-radius:9px;background:var(--brand-soft);display:flex;align-items:center;justify-content:center;font-size:16px;flex:none}
/* pricing */
body.lp .lp-pricing{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;align-items:stretch}
body.lp .lp-tier{position:relative;display:flex;flex-direction:column;background:#fff;border:1px solid var(--lp-line);border-radius:16px;padding:26px 22px;box-shadow:0 1px 2px rgba(15,33,55,.04)}
body.lp .lp-tier:hover{border-color:var(--lp-line-2)}
body.lp .lp-tier-pop{border-color:rgba(192,57,43,.5);box-shadow:0 0 0 1px rgba(192,57,43,.22),0 30px 70px -42px rgba(192,57,43,.4)}
body.lp .lp-tier-tag{position:absolute;top:-11px;left:22px;background:var(--lp-brand);color:#fff;font-size:11px;font-weight:700;letter-spacing:.3px;padding:4px 11px;border-radius:99px}
body.lp .lp-tier-name{font-size:16px;font-weight:800;color:var(--lp-navy);margin:0}
body.lp .lp-tier-for{font-size:13px;color:var(--lp-muted);margin:3px 0 0}
body.lp .lp-tier-price{margin:16px 0 0;color:var(--lp-navy)}
body.lp .lp-tier-price b{font-size:34px;font-weight:850;letter-spacing:-1px}
body.lp .lp-tier-per{font-size:13px;color:var(--lp-muted);margin-left:4px}
body.lp .lp-tier-from{font-size:12.5px;color:var(--lp-muted);font-weight:600;margin:16px 0 8px}
body.lp .lp-tier-feats{list-style:none;padding:0;margin:10px 0 22px;display:flex;flex-direction:column;gap:9px}
body.lp .lp-tier-feats li{display:flex;gap:8px;font-size:13px;line-height:1.45;color:var(--lp-text)}
body.lp .lp-tier-feats .tk{color:#1a9d5c;flex:none;font-weight:800}
body.lp .lp-tier .btn{margin-top:auto;width:100%;display:flex;justify-content:center}
body.lp .lp-pricing-note{text-align:center;color:var(--lp-text);font-size:14px;margin:24px 0 0}
body.lp .lp-pricing-foot{text-align:center;color:var(--lp-muted);font-size:12.5px;margin:7px 0 0}
@media(max-width:840px){
  body.lp .lp-pricing{grid-template-columns:1fr 1fr}
}
@media(max-width:520px){
  body.lp .lp-pricing{grid-template-columns:1fr}
}
/* proof bar: one edge-to-edge row on desktop; 2-up on tablet; stacked on mobile */
@media(max-width:1160px){
  body.lp .lp-proof-inner{justify-content:center;gap:14px 22px}
  body.lp .lp-proof-item{flex:0 0 calc(50% - 14px);white-space:normal}
}
@media(max-width:520px){
  body.lp .lp-proof-item{flex:0 0 100%}
}
/* testimonial */
body.lp .lp-quote{max-width:840px;margin:0 auto}
body.lp .lp-quote-card{background:#fff;border:1px solid var(--lp-line);border-radius:20px;padding:44px 46px;text-align:center;box-shadow:0 30px 70px -45px rgba(15,33,55,.3)}
body.lp .lp-quote-mark{font-family:var(--lp-serif);font-size:72px;line-height:.2;color:var(--lp-brand);opacity:.5;height:30px}
body.lp .lp-quote-text{font-family:var(--lp-serif);font-size:25px;line-height:1.5;letter-spacing:-.2px;color:var(--lp-navy);font-weight:500;margin:18px 0 0}
body.lp .lp-quote-by{display:inline-flex;align-items:center;gap:13px;margin-top:26px}
body.lp .lp-quote-av{width:44px;height:44px;border-radius:50%;background:var(--lp-navy);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:15px;flex:none}
body.lp .lp-quote-meta{text-align:left}
body.lp .lp-quote-meta b{display:block;color:var(--lp-navy);font-size:14.5px;font-weight:700}
body.lp .lp-quote-meta span{color:var(--lp-muted);font-size:13px}
@media(max-width:560px){body.lp .lp-quote-card{padding:32px 24px}body.lp .lp-quote-text{font-size:20px}}
/* scroll reveal — class added by JS so no-JS keeps everything visible */
body.lp .reveal{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}
body.lp .reveal.is-in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){body.lp .reveal{opacity:1!important;transform:none!important;transition:none}}
/* smooth pricing hover */
body.lp .lp-tier{transition:border-color .18s,transform .18s,box-shadow .18s}
body.lp .lp-tier:hover{transform:translateY(-3px)}

/* =========================================================
   Custom dropdowns — native <select> text can't use a web font,
   so we render our own value + menu in General Sans.
   ========================================================= */
.cselect{position:relative;display:block;width:100%}
.cselect>select{display:none}
.cselect-btn{display:flex;align-items:center;width:100%;text-align:left;padding-left:14px;padding-right:34px;cursor:pointer;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 13px center}
.cselect-btn .cs-val{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cselect-menu{position:absolute;z-index:1200;top:calc(100% + 5px);left:0;right:0;max-height:268px;overflow-y:auto;
  background:#fff;border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-2);padding:6px;display:none}
.cselect.open .cselect-menu{display:block}
.cselect-opt{padding:8px 11px;border-radius:7px;font-size:14px;line-height:1.35;cursor:pointer}
.cselect-opt:hover,.cselect-opt.hl{background:var(--blue-soft)}
.cselect-opt.sel{font-weight:700;color:var(--blue)}
.cselect-opt.is-disabled{color:var(--faint);cursor:default;background:none}

/* custom date + time pickers (same reason — native control text can't use a web font) */
.cdate,.ctime{position:relative;display:block;width:100%}
.cdate>input,.ctime>input{display:none}
.cdate-btn{display:flex;align-items:center;width:100%;text-align:left;padding-left:14px;padding-right:38px;cursor:pointer;
  background-repeat:no-repeat;background-position:right 12px center;background-size:16px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E")}
.ctime-btn{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E")}
.cdate-btn .cs-val{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cdate-btn .cs-val.ph{color:var(--faint)}
.cpop{position:absolute;z-index:1200;top:calc(100% + 5px);left:0;background:#fff;border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-2);padding:12px;display:none}
.cdate.open .cpop,.ctime.open .cpop{display:block}
.cal-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
.cal-head b{font-size:13.5px;font-weight:700;color:var(--navy)}
.cal-nav{width:30px;height:30px;border-radius:8px;border:1px solid var(--line);background:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--navy);font-size:15px}
.cal-nav:hover{background:var(--bg)}
.cal-grid{display:grid;grid-template-columns:repeat(7,34px);gap:2px}
.cal-dow{font-size:10px;font-weight:700;color:var(--faint);text-align:center;height:22px;display:flex;align-items:center;justify-content:center;text-transform:uppercase}
.cal-day{height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:13px;cursor:pointer;color:var(--ink);border:1px solid transparent}
.cal-day:hover{background:var(--blue-soft)}
.cal-day.other{color:var(--faint)}
.cal-day.today{border-color:var(--blue)}
.cal-day.sel{background:var(--blue);color:#fff;font-weight:700}
.cal-day.disabled{color:#cbd5e1;cursor:default;background:none}
.ctime .cpop{padding:6px;max-height:262px;overflow-y:auto;min-width:148px}
.ctime-opt{padding:8px 12px;border-radius:7px;font-size:14px;cursor:pointer;white-space:nowrap}
.ctime-opt:hover,.ctime-opt.hl{background:var(--blue-soft)}
.ctime-opt.sel{font-weight:700;color:var(--blue)}
/* keep paired fields' inputs level even when one label wraps to more lines */
.formrow-align .field{display:flex;flex-direction:column}
.formrow-align .field>.cdate,.formrow-align .field>.ctime,.formrow-align .field>.cselect,.formrow-align .field>.input{margin-top:auto}
