/* Elysian Tutors - shared design system
   Skin of the unified ELEVATEOS EDUCATION two-brand token system
   (design-system/unified in the ElevateOS repo; brand layer "elysian").
   Cream ground, forest-green primary, gold single accent, Fraunces display,
   Inter body. No purple, navy or teal anywhere on this brand. */
:root{
  --white:#fff;
  --ink:#12312A;
  --ink-soft:#3A4A42;
  --ink-faint:#5e7167;
  --paper:#F1F4F1;
  --card:#ffffff;
  --surface-tint:#fcfaf4;
  --green:#1f5c46;
  --green-hover:#194d3a;
  --green-deep:#023e20;
  --gold:#c08d0c;
  --gold-deep:#7d5c08;
  --gold-soft:#f9edcb;
  --wash:#e7f0ea;
  --success-soft:#e7f0ea;
  --warning-soft:#fcf1d5;
  --danger-soft:#fae7e2;
  --danger:#8c2f24;
  /* ONE oxblood, the accent. Gold is retired: green plus gold on near-white was
     the shape this estate kept converging on. On a LIGHT ground the deep oxblood
     is the readable weight, so no lightened variant is needed. */
  --oxblood:#8c2f24;
  --oxblood-deep:#6E241B;
  --line:#e6dfd0;
  --line-strong:#d6e5dc;
  --line-soft:#efe9dd;
  --container:1360px;
  --measure:70ch;
  --space-1:8px;
  --space-2:12px;
  --space-3:16px;
  --space-4:24px;
  --space-5:32px;
  --space-6:48px;
  --space-7:64px;
  --section-pad:clamp(56px,7vw,84px);
  --section-pad-mobile:52px;
  --radius:16px;
  --radius-md:12px;
  --radius-xl:20px;
  --shadow-xs:0 1px 2px rgba(18,60,45,.05),0 1px 3px rgba(18,60,45,.06);
  --shadow-sm:0 2px 4px -2px rgba(18,60,45,.07),0 5px 10px -3px rgba(18,60,45,.08);
  --shadow:0 1px 2px rgba(18,60,45,.06),0 14px 40px -18px rgba(18,60,45,.24);
  --ease:cubic-bezier(.16,1,.3,1);
  --ease-exit:cubic-bezier(.7,0,.84,0);
}
*{box-sizing:border-box}
[hidden]{display:none!important}
/* scroll-padding-top keeps anchor targets and skip-link landings clear of the
   sticky header (WCAG 2.2 SC 2.4.11 Focus Not Obscured, technique C43).
   --nav-h is measured onto :root by nav.js so it tracks the real bar height
   across breakpoints, font swaps and the signed-out -> signed-in swap. */
html{scroll-behavior:smooth;scroll-padding-top:calc(var(--nav-h,64px) + 12px)}
body{margin:0;background:var(--paper);color:var(--ink);font-family:Inter,"Helvetica Neue",Arial,sans-serif;line-height:1.6;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-size:16.5px}
::selection{background:var(--gold-soft)}
/* Two-tone focus ring, the GOV.UK/NHS solution. A single green ring disappears
   against the solid-green .btn and inside dark panels; gold carries >=3:1 on
   dark green and the dark halo carries it on cream and white.
   SC 2.4.7 Focus Visible + SC 1.4.11 Non-text Contrast. */
:focus-visible{outline:3px solid var(--gold);outline-offset:2px;box-shadow:0 0 0 6px rgba(18,35,27,.65);border-radius:3px}
/* SC 2.4.1 Bypass Blocks (Level A): a ~9-link header repeats on every page and
   there was no way past it. Offscreen rather than display:none so it stays
   focusable. */
.skip-link{position:absolute;left:-9999px;top:0;z-index:100;font-weight:600}
.skip-link:focus{left:10px;top:10px;background:var(--gold);color:var(--green-deep);padding:12px 20px;border-radius:0 0 10px 10px;text-decoration:none;box-shadow:0 0 0 3px var(--ink)}
main:focus{outline:none}
.wrap{max-width:var(--container);margin:0 auto;padding:0 22px}
.narrow{max-width:760px}
h1,h2,h3{font-family:Fraunces,Georgia,serif;font-weight:600;line-height:1.15;letter-spacing:-.014em;margin:0 0 14px;color:var(--ink);text-wrap:balance}
h1{font-size:clamp(34px,3.8vw,46px);line-height:1.1}
h2{font-size:clamp(26px,3vw,34px);line-height:1.16}
h3{font-size:20px;line-height:1.3}
p{max-width:var(--measure);margin:0 0 16px;color:var(--ink-soft)}
li{max-width:var(--measure)}
a{color:var(--green);font-weight:600}
a:hover{color:var(--green-deep)}
section{padding:var(--section-pad) 0}
.eyebrow{font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--green);margin-bottom:10px}
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:44px;background:var(--green);color:var(--white);border:1px solid var(--green);border-radius:var(--radius-md);padding:12px 24px;font-family:Inter,"Helvetica Neue",Arial,sans-serif;font-size:16px;font-weight:600;line-height:1.2;text-decoration:none;transition:transform .14s var(--ease),box-shadow .14s var(--ease),background .14s var(--ease),border-color .14s var(--ease);cursor:pointer}
.btn:hover{transform:translateY(-1px);background:var(--green-hover);border-color:var(--green-hover);color:var(--white);box-shadow:var(--shadow-sm)}
.btn:active{transform:translateY(0);box-shadow:var(--shadow-xs)}
.btn.gold{background:var(--oxblood);color:var(--paper);box-shadow:var(--shadow-sm)}
.btn.gold:hover{background:var(--gold);border-color:var(--gold-deep);filter:brightness(1.05);color:var(--paper)}
.btn.ghost{background:transparent;color:var(--green);border:1.5px solid var(--green)}
.btn.ghost:hover{background:var(--wash);color:var(--green);box-shadow:none}
.portal-links{display:grid;gap:0;margin-bottom:20px}.portal-link{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:19px 0;border-top:1px solid var(--line);color:var(--ink);text-decoration:none}.portal-link:first-child{border-top:0}.portal-link strong{display:block;font-family:Fraunces,Georgia,serif;font-size:21px}.portal-link small{display:block;color:var(--ink-faint);margin-top:4px}.portal-link:hover{color:var(--green)}.actions{display:flex;flex-wrap:wrap;gap:var(--space-1)}.secondary{background:var(--white)!important;color:var(--green)!important;border:1px solid var(--line-strong)!important}
.note{font-size:14px;color:var(--ink-soft)}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
a.card,.door-card{transition:transform .16s var(--ease),box-shadow .16s var(--ease),border-color .16s var(--ease)}
a.card:hover,.door-card:hover{transform:translateY(-2px);border-color:#d8ceba;box-shadow:0 2px 4px rgba(18,60,45,.05),0 18px 44px -16px rgba(18,60,45,.28)}
.band{background:var(--white);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-3);margin-top:30px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-6);align-items:start}
.pad{padding:26px}
.portal-main.is-authenticated{max-width:none;padding-left:clamp(22px,4vw,64px);padding-right:clamp(22px,4vw,64px)}
.portal-main.is-authenticated .pagehead{max-width:none;margin-left:0;margin-right:0}
.portal-record{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;margin-top:24px}
.portal-record label:nth-child(3),.portal-record label:nth-child(4),.portal-record button,.portal-record .err{grid-column:1/-1}
.tutor-dashboard{display:grid;gap:24px;padding:0 0 56px}
.tutor-dashboard-page .pagehead{padding:30px 0 0}
.tutor-dashboard-page #loading{padding:26px;margin-top:20px}
.tutor-dashboard-head{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;padding:20px 0 4px}
.tutor-dashboard-head h2{margin-bottom:8px}
.tutor-stats{margin:0;grid-template-columns:repeat(5,1fr)}
.stat .k,.stat .v,.stat .d{display:block}
@media (max-width:1180px) and (min-width:861px){.tutor-stats{grid-template-columns:repeat(3,1fr)}}
.tutor-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
.tutor-panel{min-width:0}
.tutor-submit{margin-top:0}
.tutor-list{display:grid;gap:0;margin-top:18px}
.tutor-list-item{display:grid;gap:3px;padding:16px 0;border-top:1px solid var(--line)}
.tutor-list-item:first-child{border-top:0;padding-top:0}
.tutor-list-item strong{font-size:16px;color:var(--ink)}
.tutor-list-item span,.tutor-list-item small{color:var(--ink-soft)}
.tutor-list-item small{font-size:14px;line-height:1.45}
.status-badge{display:inline-block;margin-left:6px;padding:2px 7px;border-radius:6px;background:var(--success-soft);color:var(--green);font-size:11px;text-transform:uppercase;letter-spacing:.08em}
.status-badge.pending{background:var(--warning-soft);color:#7b5c13}
.status-badge.declined{background:var(--danger-soft);color:#9b4337}

/* One public navigation. Portals keep the same chrome, while their private
   content stays behind sign-in. At narrower widths nav.js turns this into the
   accessible drawer. */
header.site{padding:0;border-bottom:1px solid var(--line);background:rgba(249,245,236,.94);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);position:sticky;top:0;z-index:40}
.navrow{display:flex;align-items:center;gap:16px;min-height:72px}
.brand{display:inline-flex;align-items:center;gap:10px;flex:0 0 auto;font-family:Fraunces,Georgia,serif;font-weight:600;font-size:25px;line-height:1.1;letter-spacing:-.01em;color:var(--ink);text-decoration:none;padding:10px 0;white-space:nowrap}
.brand-mark{display:block;width:44px;height:44px;flex:0 0 44px;object-fit:cover;border-radius:9px}
.brand span{color:var(--green)}
nav.top{display:flex;align-items:center;flex-wrap:wrap;gap:8px 14px;min-width:0;width:auto;margin-left:auto;justify-content:flex-start}
/* Target size: SC 2.5.8 wants 24x24 CSS px. The old padding:5px 0 with a 2px
   row-gap failed on both the target and the spacing exception once the rail
   wrapped. */
nav.top a{color:var(--ink-soft);text-decoration:none;font-size:14.5px;font-weight:500;min-height:24px;display:inline-flex;align-items:center;padding:8px 2px;margin-left:0;transition:color .14s var(--ease)}
nav.top a:hover,nav.top a[aria-current]{color:var(--green)}
nav.top a[aria-current="page"]{font-weight:600}
.nav-utility-start{margin-left:0}
/* Sign in reads as a bordered pill again, distinct from the solid CTA beside
   it: two different weights of the same shape, so which one is the primary
   action stays obvious. */
/* Drawer-only links, injected by nav.js. The desktop bar stays short by
   design; these belong to the mobile drawer, where there is no footer
   within reach. */
.nav-more{display:none}
nav.top .nav-signin{border:1px solid var(--line);border-radius:10px;padding:7px 12px;color:var(--ink)}
nav.top .nav-signin:hover{border-color:var(--green);color:var(--green);background:var(--wash)}
.nav-action{display:flex;align-items:center;justify-content:flex-end;gap:12px;position:relative;flex:0 0 auto}
.nav-action .btn{padding:10px 18px;font-size:14.5px;min-height:40px;white-space:nowrap}
.nav-action .btn:hover{color:#fff}
nav.top .btn{padding:9px 18px;font-size:14.5px;color:#fff;margin-left:0}
nav.top .btn:hover{color:#fff}
@media (max-width:1100px) and (min-width:861px){
  .navrow{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"brand brand" "nav action";align-items:center;gap:0 20px}
  .brand{grid-area:brand;justify-self:center;padding:13px 0 11px}
  nav.top{grid-area:nav;margin-left:0;padding:9px 0 11px;gap:8px 16px}
  .nav-action{grid-area:action;padding:9px 0 11px;align-self:stretch}
  /* One rule under the brand, drawn once across both cells. Two per-cell
     border-tops left a 20px hole in the line where the column gap sits, and
     sat 1px apart whenever the two cells were not the same height. */
  .navrow::after{content:"";grid-column:1/-1;grid-row:2;align-self:start;height:1px;background:var(--line-soft);pointer-events:none}
}
@media (min-width:1101px){
  /* One row, never two. Measured 2026-09-02 at 1280px: brand, seven nav items
     and the call to action came to 1048px in a 1016px column, so Sign in
     always dropped to a second line. The header may run 20px past the content
     column, and the bar cannot wrap. */
  header.site .wrap{max-width:var(--container)}  /* was a hard 1100px while the
     content column moved to 1360, so the nav stopped lining up with the page
     under it. Howard 2026-09-04: 'u need to ensure alignment'. */
  nav.top{flex-wrap:nowrap}
  nav.top a,.region summary{white-space:nowrap}
}

/* brand signature: hand-drawn gold underline (SVG stroke, scales with text) */
.uline{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12' preserveAspectRatio='none'%3E%3Cpath d='M3 8 C 45 3.5, 95 9.5, 142 6 S 190 5.5, 197 6.5' fill='none' stroke='%23c9a24b' stroke-width='3.4' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:0 100%;background-size:100% .14em;padding-bottom:.1em}

/* hero */
.hero{padding:clamp(64px,8vw,96px) 0 clamp(56px,7vw,80px);background:var(--paper)}
.hero h1{font-size:clamp(40px,4.8vw,54px);line-height:1.06}
/* align-items:start, not center: the hero copy and the sample report card must
   share a top edge. Centred, the shorter column floats down and the two read as
   two unrelated blocks rather than one row. The eyebrow is the first line of
   the left column and the card's top border is the first line of the right, so
   those are the edges that line up. */
.hero-grid{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:start}
.price-line{display:flex;flex-wrap:wrap;gap:10px;margin:20px 0 26px}
.price-chip{background:var(--card);border:1px solid var(--line);border-radius:999px;padding:8px 16px;font-size:15px;font-weight:600;color:var(--ink)}
.price-chip small{font-weight:400;color:var(--ink-faint)}
.pagehead{padding:52px 0 8px}

/* report card artifact - five-slot weekly report (shared-component anatomy) */
.report-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-xl);box-shadow:var(--shadow);padding:26px;max-width:470px;margin-left:auto;text-wrap:pretty}
.report-card .rc-head{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:1px solid var(--line);padding-bottom:12px;margin-bottom:2px;gap:10px}
.report-card .rc-eyebrow{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--green)}
.report-card .rc-title{font-family:Fraunces,Georgia,serif;font-size:19px;font-weight:600;color:var(--ink);display:block;margin-top:4px}
.report-card .rc-student{font-size:13px;color:var(--ink-faint);display:block;margin-top:2px}
.report-card .rc-date{font-size:12.5px;color:var(--ink-faint);white-space:nowrap;padding-top:2px}
.report-card h5{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--green);margin:15px 0 6px;font-weight:600}
.report-card h5 .num{color:var(--gold-deep);margin-right:6px}
.report-card p{font-size:14.5px;line-height:1.5;margin:0 0 4px;color:var(--ink)}
.report-card .quote{border-left:3px solid var(--gold);padding-left:10px;font-style:italic;color:var(--ink-soft)}
.report-card .rc-topic{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 6px}
.report-card .rc-topic span:first-child{font-size:14.5px;color:var(--ink)}
.report-card .rc-task{display:flex;align-items:flex-start;gap:9px;margin:0 0 6px}
.report-card .rc-task i{flex:none;width:14px;height:14px;margin-top:3px;border:1.5px solid var(--gold);border-radius:4px}
.report-card .rc-task span{font-size:14px;color:var(--ink)}
.report-card .rc-sign{border-top:1px solid var(--line);margin-top:16px;padding-top:12px;font-size:13px;color:var(--ink-soft);display:flex;align-items:center;gap:10px}
.report-card .rc-sign .tick{flex:none;width:26px;height:26px;border-radius:8px;background:var(--wash);display:inline-flex;align-items:center;justify-content:center}
.report-card .rc-sign strong{color:var(--ink)}
.rc-label{font-size:11.5px;color:var(--ink-faint);text-align:right;margin-top:8px;max-width:470px;margin-left:auto}
.bar{height:8px;border-radius:99px;background:var(--line-soft);overflow:hidden;margin:4px 0 10px}
.bar i{display:block;height:100%;background:var(--green);border-radius:99px}

/* deep forest panel (guarantee, All-in-One, enquiry rail) */
.panel{background:var(--green-deep);color:#fff;border-radius:var(--radius-xl);padding:clamp(24px,4vw,40px)}
.panel h2,.panel h3{color:#fff}
.panel p{color:rgba(255,255,255,.78)}
.panel .eyebrow{color:var(--gold)}
.panel a:not(.btn){color:#fff}
.check-item{display:inline-flex;align-items:center;gap:8px;font-size:14.5px;font-weight:600}
.check-item svg{flex:none}

/* numbered step timeline (how-it-works) */
.steps-timeline{display:flex;flex-direction:column}
.steps-timeline .tstep{display:flex;gap:20px;align-items:stretch}
.steps-timeline .tnum{display:flex;flex-direction:column;align-items:center;flex:none;width:44px}
.steps-timeline .tnum b{flex:none;width:44px;height:44px;border-radius:50%;background:var(--card);border:1px solid var(--line);display:inline-flex;align-items:center;justify-content:center;font-family:Fraunces,Georgia,serif;font-weight:600;font-size:19px;color:var(--gold-deep);box-shadow:var(--shadow-xs)}
.steps-timeline .tnum i{flex:1;width:1px;background:var(--line);margin:6px 0}
.steps-timeline .tstep:last-child .tnum i{display:none}
.steps-timeline .tbody{padding-bottom:26px;min-width:0}
.steps-timeline .tbody h3{font-size:19px;margin:9px 0 5px}
.steps-timeline .tbody p{font-size:14.5px;margin:0;max-width:520px}

/* subject groups */
.group-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;border-bottom:1px solid var(--line);padding-bottom:12px;flex-wrap:wrap}
.group-head h2{margin:0;font-size:26px}
.price-pill{background:var(--card);border:1px solid var(--line);border-radius:999px;padding:6px 14px;font-size:13.5px;font-weight:600;color:var(--ink);white-space:nowrap}
.price-pill small{font-weight:400;color:var(--ink-faint)}

/* trust stat strip */
.stat3{display:flex;flex-wrap:wrap;gap:14px 36px;margin-top:14px}
.stat3 .v{font-family:Fraunces,Georgia,serif;font-weight:600;font-size:26px;color:var(--ink);font-variant-numeric:tabular-nums}
.stat3 .d{display:block;font-size:13px;color:var(--ink-soft);margin-top:2px}

/* steps / tutors */
.step .n{font-family:Fraunces,Georgia,serif;font-size:30px;color:var(--gold);line-height:1}
.tutor .ph{width:84px;height:84px;border-radius:50%;background:var(--line);display:flex;align-items:center;justify-content:center;font-family:Fraunces,Georgia,serif;font-size:28px;color:var(--green);margin-bottom:14px}
.tutor .dbs{display:inline-block;font-size:12px;font-weight:600;color:var(--green);background:var(--wash);border-radius:6px;padding:3px 8px;margin-top:10px}
.tutor .creds{font-size:14.5px;color:var(--ink-soft)}

/* pricing table */
.price-table{width:100%;border-collapse:collapse;margin-top:26px;background:#fff;border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow)}
.price-table th,.price-table td{padding:16px 18px;text-align:left;border-bottom:1px solid var(--line);font-size:16px}
.price-table tbody tr{transition:background .14s var(--ease)}
.price-table tbody tr:hover{background:var(--surface-tint)}
.price-table th{font-family:Inter;font-size:13px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft);background:var(--surface-tint)}
.price-table td.big{font-family:Fraunces,Georgia,serif;font-size:22px;color:var(--ink);font-variant-numeric:tabular-nums}

/* vetting strip */
.vetting{background:#ecf1e5;color:var(--green);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.vetting .wrap{display:flex;flex-wrap:wrap;gap:14px 34px;justify-content:center;padding:16px 22px;font-size:15px;font-weight:600}

/* details / faq */
details{background:#fff;border:1px solid var(--line);border-radius:12px;padding:18px 20px;margin-bottom:12px}
details summary{font-weight:600;cursor:pointer;color:var(--ink);font-size:16.5px}
details p{margin-top:10px;font-size:15.5px}

/* forms */
form.book{padding:28px;display:grid;gap:14px;position:relative}
form.book label{font-size:13.5px;font-weight:600;color:var(--ink)}
form.book input,form.book select,form.book textarea{width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:10px;font-family:Inter;font-size:15.5px;background:#fff;color:var(--ink)}
form.book textarea{min-height:90px;resize:vertical}
form.book input:focus,form.book select:focus,form.book textarea:focus{border-color:var(--green);outline:3px solid var(--gold);outline-offset:1px}
form.book .ok{color:var(--green);font-weight:600;display:none}
form.book .err{color:#a33;font-weight:600;display:none}
.hp{position:absolute;left:-9999px;opacity:0}

/* Sign-in page: create an account first, sign in second.
   These four classes were added to login/index.html when the page was
   restructured and never given any CSS, so .signin-divider rendered as a bare
   left-aligned line of text where a centred rule was intended -- it read as a
   stray fragment rather than a separator between the two routes. */
.signin-primary{max-width:560px;margin:26px auto 0;text-align:left}
.signin-primary h2{margin:0 0 8px}
.signin-primary .btn{margin-top:4px}
.signin-aux{max-width:560px;margin:16px auto 0}
.signup-page{padding-bottom:64px}
.signup-page .pagehead{max-width:620px}
.signup-page .book{max-width:620px;margin:18px 0 0}
.signup-help{max-width:620px;border-top:1px solid var(--line);margin-top:32px;padding-top:24px}

/* A centred label with the rule running through it. The pseudo-elements are
   the rule; the span sits on the page background so the line appears to break
   for the text rather than run under it. */
.signin-divider{display:flex;align-items:center;gap:14px;max-width:560px;margin:34px auto 0;color:var(--ink-faint)}
.signin-divider::before,.signin-divider::after{content:"";flex:1;height:1px;background:var(--line)}
.signin-divider span{font-size:13.5px;letter-spacing:.02em;white-space:nowrap}

.signin-sub{text-align:center;margin:18px 0 6px}
.signin-subnote{text-align:center;max-width:560px;margin:0 auto}

@media (max-width:560px){
  .signin-divider{margin-top:26px}
}

/* two-door funnel + intake wizard */
.door-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:30px;text-align:left}
/* One card since the concierge pass of 2026-09-02: the 1fr 1fr grid above left the
   right half empty at 861px and up, and only looked right on a phone because the
   860px breakpoint collapses it. Single centred column, capped so it cannot stretch. */
.door-grid-single{grid-template-columns:minmax(0,540px);justify-content:center}
/* The closing block. Until 2026-09-03 this was a 540px card sitting above two
   full-width centred paragraphs, so the card edge and the prose edge did not
   line up at any width, and the card's own heading repeated the h2 above it.
   One column, one measure, one alignment, and no card. */
.closing{max-width:640px;margin:0 auto;text-align:left}
.closing h2{margin:4px 0 12px}
.closing p{margin:0 0 16px}
.closing-actions{display:flex;flex-wrap:wrap;gap:12px;margin:0 0 22px}
.closing .note{margin:0 0 10px}
.door-card{display:flex;flex-direction:column}
.door-card p{flex:1}
.door-card .btn{align-self:flex-start}
form.book fieldset{border:0;padding:0;margin:0;display:grid;gap:14px;min-width:0}
.wizard-steps{display:flex;gap:8px}
.wizard-steps i{height:6px;flex:1;border-radius:99px;background:var(--line-soft)}
.wizard-steps i.done{background:var(--green)}
.chip-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.chip{display:inline-flex;align-items:center;gap:7px;background:var(--wash);color:var(--green);border-radius:999px;padding:6px 12px;font-size:14px;font-weight:600}
.chip button{background:none;border:0;color:inherit;font:inherit;font-size:16px;line-height:1;cursor:pointer;padding:0}

/* footer */
footer{border-top:1px solid var(--line);padding:52px 0 36px;font-size:14px;color:var(--ink-soft);background:var(--surface-tint)}
.footcols{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr 1fr;gap:26px}
@media (max-width:1040px) and (min-width:861px){.footcols{grid-template-columns:1fr 1fr 1fr}}
.footcols h6{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink);margin:0 0 10px;font-weight:700}
.footcols a{display:block;color:var(--ink-soft);text-decoration:none;margin:6px 0;font-size:14px}
.footcols a:hover{color:var(--green)}
.footlaw{border-top:1px solid var(--line);margin-top:26px;padding-top:16px;font-size:12.5px}

/* dashboard app */
.app-shell{display:grid;grid-template-columns:230px 1fr;min-height:100vh}
.app-side{background:var(--green-deep);color:#dfeee7;padding:24px 18px}
.app-side .brand{color:#fff}
.app-side nav a{display:block;color:#bcd6cb;text-decoration:none;padding:10px 12px;border-radius:9px;margin:3px 0;font-size:15px}
.app-side nav a[aria-current],.app-side nav a:hover{background:rgba(255,255,255,.1);color:#fff}
.app-main{padding:30px clamp(18px,4vw,44px);background:var(--paper)}
.stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin:20px 0}
.stat{padding:18px 20px}
.stat .k{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft);font-weight:600}
.stat .v{font-family:Fraunces,Georgia,serif;font-size:30px;color:var(--ink);font-variant-numeric:tabular-nums}
.stat .d{font-size:13px;color:var(--green)}
.demo-banner{background:var(--gold);color:var(--paper);text-align:center;padding:9px;font-size:13.5px;font-weight:600}

/* region picker */
/* The bare 18px globe with no padding was the smallest target in the header and
   failed SC 2.5.8 on both axes; it now carries a visible "UK" label too, which
   also serves SC 2.4.4 Link Purpose (an icon alone names nothing). */
.region{position:relative;background:none;border:none;border-radius:0;padding:0;margin:0;display:flex;align-items:center}
.region summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px;min-height:24px;padding:8px;border-radius:8px;color:var(--ink-soft)}
.region summary::-webkit-details-marker{display:none}
.region summary:hover,.region[open] summary{color:var(--green)}
.region-label{font-size:13.5px;font-weight:600;letter-spacing:.02em}
.region-menu{position:absolute;right:0;top:calc(100% + 10px);background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);padding:8px;min-width:210px;z-index:50}
nav.top .region-menu a{display:block;margin:0;padding:10px 12px;border-radius:8px;font-size:14.5px;color:var(--ink);white-space:nowrap}
nav.top .region-menu a:hover{background:var(--paper);color:var(--green)}
nav.top .region-menu a[aria-current]{font-weight:600;color:var(--green)}

/* ---- auth-state swap ---------------------------------------------------
   Default (no attribute) = SIGNED OUT, so a crawler, a JS-off browser or a
   failed session fetch still gets a usable header. The inline <head> script
   flips [data-auth] from the role hint cookie before first paint, so a
   signed-in parent never sees "Sign in" flash. No !important needed:
   [data-auth] selectors are (0,2,0) and beat .btn / .nav-account at (0,1,0). */
html:not([data-auth="in"]) .auth-in{display:none}
html[data-auth="in"] .auth-out{display:none}
.nav-account{position:relative}
.nav-avatar{width:40px;height:40px;padding:0;border-radius:50%;border:1px solid var(--line);background:var(--wash);color:var(--green);font:600 14px/1 Inter,"Helvetica Neue",Arial,sans-serif;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}
.nav-avatar:hover{border-color:var(--green);background:#fff}
.nav-initials{display:inline-flex;align-items:center;justify-content:center}
.nav-menu{position:absolute;right:0;top:calc(100% + 10px);min-width:262px;max-width:min(88vw,320px);margin:0;padding:8px;list-style:none;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);z-index:50}
.nav-menu li{margin:0}
.nav-menu a,.nav-menu button{display:block;width:100%;box-sizing:border-box;text-align:left;min-height:24px;padding:10px 12px;border:0;border-radius:8px;background:none;font:500 14.5px/1.4 Inter,system-ui,sans-serif;color:var(--ink);text-decoration:none;cursor:pointer}
.nav-menu a:hover,.nav-menu button:hover{background:var(--paper);color:var(--green)}
.nav-menu .nav-id{padding:8px 12px 12px;cursor:default}
.nav-menu .nav-id strong{display:block;font-size:14.5px;color:var(--ink)}
.nav-menu .nav-id span{display:block;font-size:12.5px;color:var(--ink-faint);margin-top:2px;overflow-wrap:anywhere}
.nav-menu .nav-sep{height:1px;margin:6px 0;padding:0;background:var(--line-soft)}
.nav-menu .nav-signout{color:#a33;font-weight:600}
.nav-menu .nav-signout:hover{background:var(--danger-soft);color:#8c2f24}
/* Portal pages run full-bleed, so a 1060px header wrap would leave the wordmark
   far right of the page's own left edge. data-app lives on <html>, so the
   header block itself stays byte-identical.

   [data-auth="in"] is load-bearing, not decoration. A portal only goes
   full-bleed once it is showing content: signed OUT it renders a sign-in card
   inside .portal-main, which is `wrap narrow`. A 760px centred column. Without
   this qualifier the header ran edge-to-edge above a centred card, so the
   wordmark sat ~190px left of everything beneath it.

   Keyed on data-auth rather than :has(.portal-main.is-authenticated) precisely
   because data-auth is set from the hint cookie BEFORE first paint, while
   .is-authenticated is added later by load(). Matching on the class would be
   more direct but would widen the header a beat after the page painted, which
   is the layout shift this whole approach exists to avoid. */
html[data-app="portal"][data-auth="in"] header.site .wrap,
html[data-app="portal"][data-auth="in"] footer .wrap{max-width:none;padding-left:clamp(22px,4vw,64px);padding-right:clamp(22px,4vw,64px)}
.pay-row{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;border:1px solid var(--line);border-radius:var(--radius-md);padding:16px 18px}.pay-row strong{display:block;font-size:16px}.pay-row small{display:block;color:var(--ink-soft);margin-top:3px}.pay-actions{display:flex;gap:10px;flex-wrap:wrap}.pay-btn{background:var(--gold);color:var(--paper);border:1px solid var(--gold);border-radius:var(--radius-md);padding:11px 15px;font-family:Inter,"Helvetica Neue",Arial,sans-serif;font-size:14px;font-weight:600;cursor:pointer;min-height:44px}.pay-btn.secondary{background:var(--white);color:var(--green);border:1px solid var(--line-strong)}.pay-btn:hover{filter:brightness(1.04)}.pay-btn:active{filter:none}.pay-btn:disabled{opacity:.65;cursor:wait}
.skeleton{display:block;background:linear-gradient(100deg,var(--line-soft) 25%,var(--surface-tint) 38%,var(--line-soft) 50%,var(--line-soft) 100%);background-size:220% 100%;animation:skeleton-shimmer 1.35s ease-in-out infinite;border-radius:var(--radius-md);color:transparent!important}.skeleton-line{height:14px;margin:10px 0}.skeleton-line.short{width:38%}.skeleton-line.medium{width:65%}.skeleton-title{height:27px;width:48%;margin:5px 0 14px}.skeleton-block{height:92px;margin:14px 0}.skeleton-row{height:56px;margin:12px 0;border-radius:var(--radius-md)}.skeleton-button{display:inline-block;width:150px;height:44px;border-radius:var(--radius-md)}.loading-region[aria-busy="true"]{min-height:72px}.is-loading{position:relative;pointer-events:none}.is-loading::after{content:"";display:inline-block;width:1em;height:1em;margin-left:8px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;vertical-align:-.15em;animation:spin .7s linear infinite}.is-loading .skeleton{visibility:hidden}@keyframes skeleton-shimmer{0%{background-position:120% 0}100%{background-position:-20% 0}}@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.skeleton{animation:none}.is-loading::after{animation:none}}

/* staff dashboard (operations) */
.ops-top{display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap;padding:14px 28px;border-bottom:1px solid var(--line);background:#fff;position:sticky;top:0;z-index:30}
.ops-top .who{font-size:13.5px;color:var(--ink-soft)}
.ops-main{padding:22px 28px;display:grid;gap:18px}
.ops-tabs{display:flex;gap:8px;flex-wrap:wrap}
.ops-tabs button{border:1px solid var(--line);background:#fff;border-radius:999px;padding:8px 16px;font-family:Inter;font-size:14px;font-weight:600;color:var(--ink-soft);cursor:pointer}
.ops-tabs button[aria-selected="true"]{background:var(--green);border-color:var(--green);color:#fff}
.ops-tabs button .count{margin-left:6px;font-weight:400;opacity:.75}
.ops-split{display:grid;grid-template-columns:minmax(280px,360px) 1fr;gap:18px;align-items:start}
.ops-list{display:grid;gap:8px;max-height:72vh;overflow:auto;align-content:start}
.ops-item{width:100%;text-align:left;background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px 14px;cursor:pointer;font-family:Inter}
.ops-item:hover{border-color:var(--green)}
.ops-item[aria-selected="true"]{border-color:var(--green);box-shadow:0 0 0 2px rgba(31,92,70,.18)}
.ops-item h4{margin:0;font-size:15px;font-weight:600;color:var(--ink)}
.ops-item p{margin:3px 0 0;font-size:13px;color:var(--ink-soft)}
.ops-detail{background:#fff;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:24px;min-height:280px}
.ops-detail dl{display:grid;grid-template-columns:190px 1fr;gap:8px 16px;margin:16px 0}
.ops-detail dt{font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);padding-top:2px}
.ops-detail dd{margin:0;font-size:15px;color:var(--ink);white-space:pre-wrap}
.badge{display:inline-block;font-size:11.5px;font-weight:600;border-radius:999px;padding:3px 10px;background:var(--line-soft);color:var(--ink-soft);vertical-align:middle}
.badge.green{background:var(--wash);color:var(--green)}
.badge.gold{background:var(--gold-soft);color:var(--gold-deep)}
.badge.red{background:#f7e2de;color:#a33}
.toast{position:fixed;bottom:24px;right:24px;z-index:100;background:var(--green-deep);color:#fff;font:600 14.5px Inter;padding:13px 18px;border-radius:12px;box-shadow:var(--shadow);opacity:0;transform:translateY(8px);transition:opacity .25s ease,transform .25s ease;max-width:360px}
.toast.show{opacity:1;transform:none}
.toast.bad{background:#8c2f24}
.ops-main .stat-row{grid-template-columns:repeat(6,1fr)}
.stat-link{text-align:left;font-family:Inter;cursor:pointer;border:1px solid var(--line)}
.stat-link:hover{border-color:var(--green)}
.stat-link .k,.stat-link .v,.stat-link .d{display:block}
@media (max-width:900px){.ops-split{grid-template-columns:1fr}.ops-list{max-height:40vh}.ops-detail dl{grid-template-columns:1fr}.ops-main .stat-row{grid-template-columns:1fr 1fr}}

@media (max-width:860px){
  /* Inline links can otherwise render as 18-20px text boxes, below the 24px
     minimum touch target. Keep desktop typography unchanged and leave card
     links and buttons to their component rules. */
  main a:not(.btn):not(.card),footer a{min-height:24px;display:inline-flex;align-items:center}

  .hero-grid,.grid2{grid-template-columns:1fr}
  .grid3{grid-template-columns:1fr}
  .door-grid{grid-template-columns:1fr}
  .report-card{margin:30px auto 0}
  .rc-label{margin:8px auto 0}
  .stat-row{grid-template-columns:1fr 1fr}
  .footcols{grid-template-columns:1fr 1fr}
  .app-shell{grid-template-columns:1fr}
  .app-side{display:none}
  .portal-record{grid-template-columns:1fr}
  .portal-record label:nth-child(3),.portal-record label:nth-child(4),.portal-record button,.portal-record .err{grid-column:auto}
  .tutor-grid{grid-template-columns:1fr}
  .tutor-stats{grid-template-columns:1fr}
  .tutor-dashboard-head{display:block}
  .tutor-dashboard-head .btn{margin-top:10px}
  section{padding:var(--section-pad-mobile) 0}
}

/* mobile nav, burger + left drawer, built by nav.js on pages that load it.
   Desktop is untouched: these only apply under .has-mobile-nav on narrow
   viewports. Bar layout is burger | wordmark | Sign in.

   860px covers every phone in portrait (360-448) and iPad portrait. Known and
   accepted: between 861 and ~950 the desktop rail wraps to two rows, which
   affects large phones in landscape (932) and narrow desktop windows. Raising
   this to 960 would close that gap if it ever matters. */
/* First-paint guard, set by nav.js and removed after two frames. Without it,
   switching nav.top to the fixed drawer on load animates it out of its desktop
   position. The nav appears to fly off to the left on every page load.
   !important because it must beat the [data-nav-open] and reduced-motion rules. */
.nav-booting nav.top,
.nav-booting .nav-toggle span,
.nav-booting .nav-scrim{transition:none!important}
.nav-toggle,.nav-signin{display:none}
/* Sits BELOW header.site (z-index 40). header.site is a stacking context, so
   the drawer's z-index is scoped inside it and the header's own z-index is what
   competes with the scrim. Keeping the scrim underneath means the order never
   depends on a value that toggles, z-index cannot animate, so a bump-on-open
   would snap back mid-close and cover the drawer on its way out. */
.nav-scrim{display:none;position:fixed;inset:0;z-index:25;background:rgba(18,60,45,.4);opacity:0;visibility:hidden}
@media (max-width:860px){
  /* fades rather than display-toggling, so it leaves the way it arrived */
  .nav-scrim{display:block;transition:opacity .26s var(--ease-exit),visibility 0s linear .26s}
  .nav-scrim.is-open{opacity:1;visibility:visible;transition:opacity .26s var(--ease),visibility 0s}
  /* a backdrop-filter would make the header the containing block for the
     fixed drawer, clipping it to the bar's height, so mobile uses a solid bar */
  header.site.has-mobile-nav{background:var(--paper);backdrop-filter:none;-webkit-backdrop-filter:none}
  /* Flatten the desktop two-tier grid back to one bar. `grid-template-areas:
     none` is load-bearing: without it the desktop areas survive, the burger
     has no area and is placed by auto-flow into a phantom row, and the bar
     grows a blank strip above the wordmark. */
  .has-mobile-nav .navrow{display:grid;grid-template-areas:none;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;min-height:60px}
  .has-mobile-nav .brand{grid-area:auto;justify-self:start}
  .has-mobile-nav nav.top{grid-area:auto}
  /* The action cell loses the desktop hairline when it sits in the bar. */
  .has-mobile-nav .nav-action{grid-area:auto;border-top:0;padding:0}
  /* Left-aligned, not centred: NN/g measured users far likelier to fail to
     reach home from a centred logo. */
  .has-mobile-nav .brand{padding:12px 0;text-align:left;font-size:21px}
  /* 44x44 clears Apple HIG 44pt and SC 2.5.5 Target Size (Enhanced). */
  .has-mobile-nav .nav-toggle{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;width:44px;height:44px;padding:0;background:transparent;border:1px solid var(--line);border-radius:10px;color:var(--ink);cursor:pointer}
  .has-mobile-nav .nav-toggle:hover{border-color:var(--green);color:var(--green)}
  /* closing: bars un-rotate first, then the middle bar fades back in */
  .has-mobile-nav .nav-toggle span{display:block;width:18px;height:1.5px;background:currentColor;border-radius:2px;transition:transform .26s var(--ease-exit),opacity .12s var(--ease-exit) .14s}
  /* opening: the middle bar clears immediately as the X forms */
  .has-mobile-nav .nav-toggle[aria-expanded="true"] span{transition:transform .26s var(--ease),opacity .12s var(--ease)}
  .has-mobile-nav .nav-toggle span+span{margin-top:4.5px}
  .has-mobile-nav .nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
  .has-mobile-nav .nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
  .has-mobile-nav .nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
  /* The bar keeps the action cell (CTA or avatar), the most valuable control,
     where it used to keep Sign in and hide the CTA in the drawer. */
  .has-mobile-nav .nav-action .btn{padding:11px 16px;font-size:14.5px;min-height:44px}
  .has-mobile-nav .nav-avatar{width:44px;height:44px}
  /* the nav rail becomes a slide-in drawer */
  .has-mobile-nav nav.top{position:fixed;top:var(--nav-h,64px);left:0;bottom:0;width:min(84vw,320px);display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;flex-wrap:nowrap;gap:0;border-top:0;border-right:1px solid var(--line);background:var(--paper);box-shadow:0 0 60px -14px rgba(18,60,45,.4);padding:22px 22px 28px;overflow-y:auto;z-index:60;transform:translateX(-100%);visibility:hidden;transition:transform .26s var(--ease-exit),visibility 0s linear .26s}
  .has-mobile-nav[data-nav-open] nav.top{transform:none;visibility:visible;transition:transform .26s var(--ease),visibility 0s}
  /* the panel takes focus on open (see nav.js) but is not a control the user
     tabs to, so it should not draw the global focus ring, links inside it
     still get theirs normally */
  .has-mobile-nav nav.top:focus,.has-mobile-nav nav.top:focus-visible{outline:none}
  .has-mobile-nav nav.top a{display:block;margin:0;padding:14px 0;font-size:16px;color:var(--ink);border-bottom:1px solid var(--line-soft)}
  .has-mobile-nav nav.top a:hover,.has-mobile-nav nav.top a[aria-current]{color:var(--green)}
  .has-mobile-nav nav.top{overscroll-behavior:contain}
  /* Drawer order: the five primary links, a rule, then the utility group. */
  /* Group boundaries in the drawer: the row above already draws its rule, so a
     group opens with clear space and no second line. Two rules with a 14px hole
     between them was the "weird line break" Georgio saw on 2026-09-02. */
  .has-mobile-nav nav.top .nav-utility-start{order:1;margin-left:0;margin-top:14px;padding-top:14px;border-top:0}
  /* Sign in is an OUTLINED BUTTON on desktop and a plain row in the drawer.
     Without this reset it was neither: the desktop rule (nav.top .nav-signin)
     sets a border on all four sides and 7px/14px padding, while the drawer's
     own rule (.has-mobile-nav nav.top a) is more specific on padding alone --
     so the box survived and the horizontal inset did not, leaving a full-width
     270px outline with the label jammed against its left edge. In the drawer it
     is one item in a list of items, so it gets the same divider as the rest. */
  .has-mobile-nav nav.top .nav-signin{order:2;border:0;border-bottom:1px solid var(--line-soft);border-radius:0;padding:14px 0}
  .has-mobile-nav nav.top .nav-more{order:2;display:block;margin-top:14px;padding-top:0;border-top:0}
  .has-mobile-nav nav.top .nav-more a{display:block;padding:14px 0;font-size:16px;border-bottom:1px solid var(--line-soft)}
  /* region picker last, opening inline rather than as a popover */
  .has-mobile-nav nav.top .region{order:3;display:block;margin-top:14px}
  .has-mobile-nav nav.top .region-menu{position:static;min-width:0;margin-top:8px;box-shadow:none}
  .has-mobile-nav nav.top .region-menu a{padding:12px;font-size:15px;border-bottom:0}
}
/* Reduce Motion (macOS: Accessibility > Display > Reduce motion) asks for no large
   translational movement. It does not ask for zero feedback. So the drawer
   cross-fades in place instead of snapping open with no animation at all.
   MUST stay scoped to the mobile width: unscoped, the opacity:0 below would hide
   the DESKTOP nav outright for anyone with the preference set. Selectors also have
   to match the [data-nav-open] specificity or the slide would survive. */
@media (max-width:600px){
  /* Phone bar budget. Measured 2026-09-02 at 375px: the column is 331px and
     toggle, mark, full wordmark and the call to action came to 420px, so the
     button sat on top of the wordmark. "Tutors" leaves the bar first; the
     drawer, the footer and the page title still carry the full name. */
  .has-mobile-nav .brand span{display:none}
  .has-mobile-nav .nav-action .btn{padding:10px 13px;font-size:13.5px}
}
@media (max-width:420px){
  .has-mobile-nav .navrow{gap:8px}
  .has-mobile-nav .brand{gap:8px;font-size:20px}
  .has-mobile-nav .brand-mark{width:40px;height:40px;flex-basis:40px}
  .has-mobile-nav .nav-toggle{width:40px;height:40px}
  .has-mobile-nav .nav-action .btn{padding:10px 11px;font-size:13px}
}
@media (max-width:340px){
  /* Mark only. The wordmark stays in the DOM for assistive tech. */
  .has-mobile-nav .brand{gap:0;font-size:0}
}
@media (max-width:860px) and (prefers-reduced-motion:reduce){
  .has-mobile-nav nav.top{transform:none;opacity:0;transition:opacity .18s linear,visibility 0s linear .18s}
  .has-mobile-nav[data-nav-open] nav.top{transform:none;opacity:1;transition:opacity .18s linear,visibility 0s}
  .has-mobile-nav .nav-toggle span,
  .has-mobile-nav .nav-toggle[aria-expanded="true"] span{transition:opacity .12s linear}
  .nav-scrim{transition:opacity .18s linear,visibility 0s linear .18s}
  .nav-scrim.is-open{transition:opacity .18s linear,visibility 0s}
}

/* weekly lesson reports (tutor form, staff approval queue, family timeline) */
.muted{font-size:14px;color:var(--ink-soft)}
.slot-label{display:block;font-size:13.5px;font-weight:600;color:var(--ink);margin:6px 0 8px}
.report-rows{display:grid;gap:8px;margin-bottom:8px}
.report-row{display:grid;grid-template-columns:1fr auto auto;gap:8px;align-items:center}
.report-row input,.report-row select{width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:10px;font-family:Inter;font-size:14.5px;background:#fff;color:var(--ink)}
.report-row .btn,.report-row .row-remove{padding:8px 12px;font-size:13px}
.report-row.task{grid-template-columns:1fr 1fr auto}
.report-add{justify-self:start;padding:8px 14px;font-size:13.5px}
.conf-badge{display:inline-block;margin-left:6px;padding:2px 8px;border-radius:999px;font-size:11.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;vertical-align:middle}
.conf-badge.confident{background:var(--wash);color:var(--green)}
.conf-badge.progressing{background:var(--gold-soft);color:var(--gold-deep)}
.conf-badge.struggling{background:#f7e2de;color:#a33}
.status-badge.sent{background:#eef2fb;color:#2f4b8f}
.weekly-report{border-top:1px solid var(--line);padding:20px 0}
.weekly-report:first-child{border-top:0;padding-top:6px}
.weekly-report header{display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;align-items:baseline}
.weekly-report h5{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);margin:14px 0 4px;font-weight:600}
.weekly-report p{margin:0 0 4px}
.weekly-report ul{margin:0;padding-left:20px}
.weekly-report li{margin:2px 0}
.report-cta{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:12px}
.report-review .slot-label{margin-top:14px}
@media (max-width:640px){
  .report-row,.report-row.task{grid-template-columns:1fr}
  .report-cta{align-items:flex-start;flex-direction:column}
}

/* ---- account settings ---------------------------------------------------
   Layout only: every control reuses .card/.pad/.btn/.note/.chip so settings
   does not become a second visual language. All classes are set-* prefixed so
   nothing above can be disturbed. The annotated two-column shape (a rail that
   names the sections, cards on the right) is a settings-page signature and is
   deliberately used nowhere else on the site. */
.set-grid{display:grid;grid-template-columns:minmax(180px,240px) minmax(0,1fr);gap:26px 40px;align-items:start;padding-bottom:56px}
.set-aside{position:sticky;top:calc(var(--nav-h,64px) + 20px)}
.set-rail{display:flex;flex-direction:column;gap:2px}
.set-rail a{color:var(--ink-soft);text-decoration:none;font-size:14.5px;font-weight:500;padding:8px 10px;border-radius:8px;min-height:24px;display:flex;align-items:center}
.set-rail a:hover{color:var(--green);background:var(--wash)}
.set-card{margin-bottom:20px}
.set-card-head h2{margin-bottom:4px}
.set-card-head .note{margin:0 0 18px}
.set-row{display:block;margin:0 0 16px}
.set-label{display:block;font-size:13.5px;font-weight:600;color:var(--ink);margin-bottom:6px}
.set-row input,.set-row select{width:100%;max-width:420px;padding:11px 13px;border:1px solid var(--line);border-radius:10px;background:#fff;font:400 15.5px/1.4 Inter,system-ui,sans-serif;color:var(--ink)}
.set-row input[type=checkbox]{width:auto}
.set-row input:focus,.set-row select:focus{border-color:var(--green);outline-offset:1px}
.set-hint{display:block;margin-top:6px}
.set-static{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.set-actions{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:18px;padding-top:16px;border-top:1px solid var(--line-soft)}
/* The button is disabled until a card is dirty, so the resting state must not
   look broken - it looks quiet, not dead. */
.set-actions .btn[disabled]{opacity:.45;cursor:default}
.set-status{font-size:14px;color:var(--ink-soft);min-height:20px}
.set-status.is-ok{color:var(--green);font-weight:600}
.set-status.is-err{color:#a33;font-weight:600}
.set-chip{display:inline-block;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:600;letter-spacing:.03em;text-transform:uppercase}
.set-chip.is-ok{background:var(--wash);color:var(--green)}
.set-chip.is-warn{background:var(--warning-soft);color:#7b5c13}
.set-chip.is-lock{background:var(--wash);color:var(--ink-soft);text-transform:none;letter-spacing:0;font-weight:500}
.set-toggles{display:flex;flex-direction:column}
.set-toggle{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:14px 0;border-bottom:1px solid var(--line-soft)}
.set-toggle:last-child{border-bottom:0}
.set-toggle-main{display:flex;align-items:flex-start;gap:12px;cursor:pointer;flex:1 1 auto}
.set-toggle-main input{margin-top:3px;width:18px;height:18px;flex:0 0 auto}
.set-toggle-main strong{display:block;font-size:15px}
.set-toggle-main .note{margin:2px 0 0}
.set-toggle-main input[disabled]{cursor:default}
.set-child-box{padding:18px 0;border-bottom:1px solid var(--line-soft)}
.set-child-box:last-child{border-bottom:0}
.set-links{display:flex;flex-wrap:wrap;gap:8px 20px;margin-bottom:14px}
.set-devices{margin-top:22px;padding-top:18px;border-top:1px solid var(--line-soft)}
/* Unread badge on the header avatar. */
.nav-avatar{position:relative}
.nav-badge{position:absolute;top:-2px;right:-2px;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:#a33;color:#fff;font:600 11px/18px Inter,system-ui,sans-serif;text-align:center;border:2px solid var(--paper)}
@media (max-width:760px){
  .set-grid{grid-template-columns:1fr;gap:10px 0}
  .set-aside{position:static;margin-bottom:8px}
  .set-rail{flex-direction:row;flex-wrap:wrap;gap:6px}
  .set-rail a{border:1px solid var(--line);padding:8px 12px}
}
.mk-earn-stats{grid-template-columns:repeat(4,1fr);margin:18px 0 6px}
@media (max-width:900px){.mk-earn-stats{grid-template-columns:repeat(2,1fr)}}
.mk-earn-lines{margin-top:16px}
.lp-opt{display:block;margin:8px 0;font-size:15px;color:var(--ink)}
.lp-opt textarea{width:100%;min-height:80px;margin-top:6px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;font:400 15px/1.5 Inter,system-ui,sans-serif}
/* A button that must read as a link: it performs an action (re-sends a code)
   so it cannot be an <a>, but making it look like a button would give the page
   two competing primary actions. */
.linklike{background:none;border:0;padding:0;font:inherit;color:var(--green);font-weight:600;cursor:pointer;text-decoration:underline}
.linklike:hover{color:var(--green-deep)}
.linklike[disabled]{opacity:.5;cursor:default}

/* ---- booking wizard -----------------------------------------------------
   The booking page is a sequence of pages, not one long scroll: a step cannot
   be opened until the ones before it are complete, so the person is never
   choosing a time for a subject they have not picked. */
.bk-wizard{display:flex;list-style:none;margin:0 0 26px;padding:0;gap:6px;flex-wrap:wrap}
.bk-wizard li{display:flex;align-items:center;gap:8px;padding:8px 14px 8px 8px;border-radius:999px;color:var(--ink-faint);font-size:14px;font-weight:600;cursor:default}
.bk-wizard li.is-done,.bk-wizard li.is-current{color:var(--ink)}
.bk-wizard li.is-done{cursor:pointer}
.bk-wizard li.is-current{background:var(--wash)}
.bk-dot{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:50%;border:1px solid var(--line);background:#fff;font-size:13px;flex:0 0 auto}
.bk-wizard li.is-current .bk-dot{background:var(--green);border-color:var(--green);color:#fff}
/* A completed step shows a tick rather than its number: the number is only
   useful while it is still ahead of you. */
.bk-wizard li.is-done .bk-dot{background:var(--wash);border-color:var(--green);color:var(--green);font-size:0}
.bk-wizard li.is-done .bk-dot::after{content:"\2713";font-size:14px}
.bk-wizard li.is-locked{opacity:.45}
.bk-nav{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:24px;padding-top:20px;border-top:1px solid var(--line-soft)}
.bk-nav .btn[disabled]{opacity:.45;cursor:default;transform:none;box-shadow:none}
.bk-step h2:focus{outline:none}
@media (max-width:560px){
  .bk-dot-label{display:none}
  .bk-wizard li{padding:8px}
}

/* Role doors, shared by /login/ and /join/.
   These lived inline in login/index.html until /join/ needed the same three
   doors. A second inline copy is how the header ended up with seven variants,
   so they move here once and both pages reference them. */
.door-grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:34px}
@media (max-width:780px){.door-grid3{grid-template-columns:1fr}}
.door{display:flex;flex-direction:column;gap:12px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-xs);padding:24px;color:var(--ink);text-decoration:none;transition:transform .16s var(--ease),box-shadow .16s var(--ease),border-color .16s var(--ease)}
.door:hover{transform:translateY(-2px);border-color:var(--green);box-shadow:0 2px 4px rgba(18,60,45,.05),0 18px 44px -16px rgba(18,60,45,.28);color:var(--ink)}
.door .ic{width:44px;height:44px;border-radius:12px;background:var(--wash);display:inline-flex;align-items:center;justify-content:center}
.door h2{font-size:20px;margin:0}
.door p{font-size:14px;line-height:1.5;margin:0;flex:1;color:var(--ink-soft)}
.door .go{font-size:14px;font-weight:600;color:var(--green);display:inline-flex;align-items:center;gap:6px}
.door:hover .go{color:var(--green-deep)}
/* /join/'s doors are <button>, because choosing a role reveals a panel rather
   than navigating. A button inherits none of the page's typography and comes
   with its own border and centred text, so it has to be reset back to the
   anchor's appearance or the three doors do not match each other. */
button.door{font:inherit;text-align:left;cursor:pointer;width:100%;appearance:none}
button.door:focus-visible{outline:2px solid var(--green);outline-offset:2px}

/* Tick lists on the tutor application (/tutor-application.html).
   These MUST outrank `form.book input, form.book select, form.book textarea`
   above, which sets width:100% with a 12px padded border. A checkbox caught by
   that rule renders as a full-width rounded box with the tick stranded in the
   middle and its own label text pushed outside the border. Reported as "looks
   really weird" 2026-08-14, and it was: the big rounded pill on screen was the
   checkbox itself. `form.book .chk input` beats it on specificity; do not
   weaken this selector back to `.chk input`. */
.chk{display:inline-flex;align-items:center;gap:9px;font-size:14px;font-weight:500;color:var(--ink);background:var(--card);border:1px solid var(--line);border-radius:999px;padding:9px 16px;margin:0 8px 8px 0;cursor:pointer;min-height:40px;line-height:1.2;white-space:nowrap;transition:border-color .16s var(--ease),background .16s var(--ease)}
form.book .chk input,form.book .chk input[type="checkbox"]{width:17px;height:17px;min-width:17px;flex:0 0 17px;margin:0;padding:0;border-radius:4px;accent-color:var(--green);background:#fff}
.chk:hover{border-color:var(--green)}
.chk:has(input:checked){border-color:var(--green);background:var(--wash)}
.chk:focus-within{outline:2px solid var(--green);outline-offset:2px}
/* The groups wrap as a row of pills, not a stacked column of full-width rows. */
.chkgroup{display:flex;flex-wrap:wrap;border:0;padding:0;margin:0 0 14px}
.chkgroup legend{padding:0;margin-bottom:8px;font-size:13.5px;font-weight:600;color:var(--ink-soft)}
@media (max-width:560px){.chk{white-space:normal}}


/* ---------------------------------------------------------------------------
   SHARED TOKEN CONTRACT (added 2026-09-04)
   Same NAMES across every property, different VALUES in each. Aliases onto this
   site's own tokens, so no pixel changes: they only let a component written here
   work in another property without a rename. Measured 2026-09-04: the design
   systems shared hue and shared no variable names, so nothing ported.
   Contract: ~/Downloads/Personal/domain-parse/tokens-contract.css
   --------------------------------------------------------------------------- */
:root {
  --paper-sunk: var(--wash);
  --ink-quiet: var(--ink-soft);
  --rule: var(--line);
  --accent: var(--gold);
}


/* ---------------------------------------------------------------------------
   THE SUPERVISION (2026-09-04). Direction 3: a college room, a hard question,
   handwriting in the margin. It sits in its OWN full-width band, not inside the
   hero column: in the hero it made the left side twice the height of the right
   and left a large void beside the report card.
   --------------------------------------------------------------------------- */
.supervision-band { border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  background:var(--card); padding:34px 0; }
.supervision { border-left:2px solid var(--oxblood); padding:2px 0 2px 20px;
  display:grid; grid-template-columns:1fr 1fr; gap:0 34px; align-items:start; }
.sv-cap { grid-column:1 / -1; font-family:Inter,"Helvetica Neue",Arial,sans-serif; font-size:11px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink-faint); margin:0 0 14px; }
.sv-turn { display:contents; }
.sv-turn > div { padding:10px 0; border-bottom:1px solid var(--line-soft); }
.sv-turn > p.sv-note { padding:10px 0; border-bottom:1px solid var(--line-soft); margin:0; }
.sv-who { font-family:Inter,"Helvetica Neue",Arial,sans-serif; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-faint); display:block; margin-bottom:5px; }
.sv-said { font-family:Fraunces,Georgia,serif; font-size:1.04rem; line-height:1.5; color:var(--ink); margin:0; }
.sv-note { font-family:'Bradley Hand','Segoe Script','Snell Roundhand',cursive,Fraunces,Georgia,serif;
  color:var(--oxblood); font-size:.98rem; line-height:1.4; transform:rotate(-.7deg); }
@media (max-width:760px){ .supervision{ grid-template-columns:1fr; gap:0; }
  .sv-turn > div, .sv-turn > p.sv-note { border-bottom:0; padding:6px 0; } }


/* ---------------------------------------------------------------------------
   THE TUTOR WRITES IN THE MARGIN AS YOU READ (added 2026-09-05)
   Direction 3: "with the tutor's annotations appearing beside it as you read."
   The transcript sits below the fold in its own band, so this is scroll-driven
   rather than a fixed timeline: the oxblood rule draws down the left edge and
   each annotation arrives beside its turn, slightly late, the way a note is
   written after the sentence it answers.
   --------------------------------------------------------------------------- */
.supervision { --sv-draw: 0; }
.supervision.sv-in { --sv-draw: 1; }
.supervision { border-left-color: transparent; position: relative; }
.supervision::before { content: ""; position: absolute; left: -2px; top: 0; width: 2px;
  height: 100%; background: var(--oxblood); transform: scaleY(0); transform-origin: top;
  transition: transform .8s ease-out; }
.supervision.sv-in::before { transform: scaleY(1); }
.supervision .sv-note { opacity: 0; transform: translateY(6px) rotate(-.7deg);
  transition: opacity .5s ease-out, transform .5s ease-out; }
.supervision.sv-in .sv-note { opacity: 1; transform: rotate(-.7deg); }
.supervision.sv-in .sv-turn:nth-child(2) .sv-note { transition-delay: .45s; }
.supervision.sv-in .sv-turn:nth-child(3) .sv-note { transition-delay: .95s; }
.supervision.sv-in .sv-turn:nth-child(4) .sv-note { transition-delay: 1.45s; }
@media (prefers-reduced-motion: reduce) {
  .supervision::before { transform: scaleY(1); transition: none; }
  .supervision .sv-note { opacity: 1; transform: rotate(-.7deg); transition: none; }
}
