/* ================================================================
   Fonts, served from this origin.

   These were a <link> to fonts.googleapis.com, which cost every page a
   render-blocking request to a third party before it could paint text —
   and fonts.googleapis.com is unreachable from mainland China, where a
   reader of the Simplified bundle would have waited for it to time out
   before seeing anything at all. A typeface is not worth a blank page.

   Generated from, and regenerated by re-fetching:
     https://fonts.googleapis.com/css2?family=Literata:opsz,wght@7..72,300;7..72,400&family=Archivo:wght@400;500;600&display=swap
   with a browser User-Agent, then rewriting each src to /static/fonts/.
   The unicode-range declarations are kept verbatim, so a browser still
   downloads only the subsets the page actually uses — latin alone is
   ~104KB of the 311KB on disk. Both families are SIL Open Font License
   1.1; see fonts/OFL.txt.
   ================================================================ */

/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-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;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-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;
}

/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-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;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-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;
}

/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-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;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/static/fonts/archivo-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;
}

/* cyrillic-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

/* cyrillic */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* greek-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}

/* greek */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}

/* vietnamese */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-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;
}

/* latin */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(/static/fonts/literata-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;
}

/* cyrillic-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

/* cyrillic */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* greek-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}

/* greek */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}

/* vietnamese */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-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;
}

/* latin */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/static/fonts/literata-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;
}

/* ================================================================
   Tokens.

   Every colour in this file goes through one of these, which is what
   makes a theme a block of variables rather than a second stylesheet.
   The rule for adding one: if a value would have to change in ANY
   theme, it is a token — including the white that sits on top of
   --ink, because in a dark theme --ink is the light colour and a
   literal #fff there is invisible text.
   ================================================================ */
:root{
  --bg:#F7F6F3; --panel:#FFFFFF; --ink:#1A1815; --ink2:#4A453E; --grey:#7A736A; --faint:#A9A299;
  --line:#E5E1D9; --line2:#F1EEE8;
  --ai:#33528F; --ai-bg:#EDF1F9; --ai-line:#C3CFE5;
  --human:#9B3232; --human-bg:#FAEDEC; --human-line:#E2C4C1;
  --ok:#2E6B52; --ok-bg:#E9F2ED;
  --sans:"Archivo",system-ui,sans-serif; --serif:"Literata",Georgia,serif;

  /* Text that sits ON the --ink surface (buttons, the sign-in aside, the avatar). */
  --on-ink:#FFFFFF;
  --on-ink-soft:rgba(255,255,255,.86); --on-ink-mute:rgba(255,255,255,.72);
  --on-ink-faint:rgba(255,255,255,.5); --on-ink-dim:rgba(255,255,255,.4);
  --on-ink-line:rgba(255,255,255,.13); --on-ink-link:rgba(255,255,255,.6);

  /* Surfaces and depth. --glass is a backdrop-filter, `none` everywhere but one theme. */
  --shadow:0 1px 3px rgba(26,24,21,.08);
  --veil:rgba(247,246,243,.93);
  --glass:none;
  --bg-image:none;
  --radius:3px;
  --focus:2px;
  --border:1px;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{margin:0;font-weight:600}
p{margin:0}
button{font-family:inherit}

/* ---- login ---- */
.login{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:40px 20px}
.login-box{width:100%;max-width:400px}
.login .brand{font-family:var(--serif);font-weight:400;font-size:32px;letter-spacing:-.015em;margin-bottom:2px}
.login .cn{font-family:var(--serif);font-size:17px;color:var(--faint);letter-spacing:.2em;margin-bottom:6px}
.login .tag{font-size:13.5px;color:var(--grey);margin-bottom:34px}
.field{margin-bottom:14px}
/* These three describe a labelled text box, and they must not reach an option row.
 *
 * `.opt` is itself a <label> and its control is a checkbox or a radio, so as bare descendant
 * selectors these out-specify `.opt` (two components to one) and win: the label loses the flex
 * row it declares, and the checkbox is stretched to `width:100%` with 11px of padding and a
 * border, so it eats the line and shoves the wording out of it. Every option list in the app
 * sits inside a `.field` — the profile's levels, the wizard's span and its inherited-tier
 * trees, Layer 2's scope modes — so the leak was general, not local to one form.
 */
.field label:not(.opt){display:block;font-size:12px;font-weight:500;color:var(--ink2);margin-bottom:6px}
.field input:not([type=checkbox]):not([type=radio]){width:100%;padding:11px 13px;
  border:1px solid var(--line);background:var(--panel);
  font-family:inherit;font-size:14px;color:var(--ink);border-radius:3px}
.field input:not([type=checkbox]):not([type=radio]):focus{outline:2px solid var(--ai);
  outline-offset:-1px;border-color:transparent}
.login .foot{margin-top:26px;padding-top:20px;border-top:1px solid var(--line);font-size:12.5px;color:var(--faint)}
.roles{display:flex;gap:6px;margin-top:10px;flex-wrap:wrap}
.roles button{font-size:12px;padding:6px 11px;border:1px solid var(--line);background:var(--panel);
  color:var(--ink2);cursor:pointer;border-radius:3px}
.roles button:hover{border-color:var(--ink2)}

/* ---- app shell ---- */
.app{display:none;min-height:100vh}
.app.on{display:grid;grid-template-columns:216px 1fr}
.side{background:var(--panel);border-inline-end:1px solid var(--line);padding:18px 0;
  position:sticky;top:0;height:100vh;overflow-y:auto}
.side .brand{font-family:var(--serif);font-weight:400;font-size:19px;padding:0 20px 4px}
.side .brand i{font-style:normal;color:var(--faint);font-size:13px;margin-inline-start:6px;letter-spacing:.14em}
.side .role{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--faint);padding:0 20px 16px;border-bottom:1px solid var(--line2);margin-bottom:12px}
.nav{padding:0 10px}
.nav .grp{font-size:10.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint);padding:14px 10px 6px}
.nav button{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  font-size:13.5px;color:var(--ink2);padding:8px 10px;border-radius:3px;line-height:1.4}
.nav button:hover{background:var(--line2)}
.nav button[aria-current="true"]{background:var(--ink);color:var(--on-ink);font-weight:500}
.nav button:focus-visible{outline:2px solid var(--ai);outline-offset:-2px}
/* A step already passed, offered again because Build and Evaluate cycle. Quieter than a step
   of its own so the ordered list still reads as ordered, and never highlighted as current. */
.nav .navcycle button{font-size:12.5px;color:var(--faint);padding-top:6px;padding-bottom:6px}
.nav .navcycle button span[aria-hidden]{margin-inline-end:4px;opacity:.8}
.sideout{margin-top:22px;padding:14px 20px 0;border-top:1px solid var(--line2)}
.sideout button{background:none;border:0;color:var(--grey);font-size:12.5px;cursor:pointer;padding:0}

.top{background:var(--panel);border-bottom:1px solid var(--line);padding:0 30px;
  display:flex;align-items:center;justify-content:space-between;height:56px;position:sticky;top:0;z-index:5}
.top .crumb{font-size:13px;color:var(--grey)}
.top .crumb b{color:var(--ink);font-weight:500}
.who{display:flex;align-items:center;gap:9px;font-size:13px}
/* ----------------------------------------------------------------
   Language and Appearance, as icons beside the person they belong
   to. A <details> so it opens without JavaScript; app.js only adds
   closing on Escape and on a click elsewhere.
   ---------------------------------------------------------------- */
.topright{display:flex;align-items:center;gap:4px}
.pick{position:relative}
.pick>summary{list-style:none;display:flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:8px;cursor:pointer;color:var(--ink2)}
.pick>summary::-webkit-details-marker{display:none}
.pick>summary::marker{content:""}
.pick>summary:hover{background:var(--line2);color:var(--ink)}
.pick>summary:focus-visible{outline:2px solid var(--ai);outline-offset:1px}
.pick[open]>summary{background:var(--line2);color:var(--ink)}
.pickmenu{position:absolute;right:0;top:calc(100% + 7px);z-index:60;min-width:174px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:6px;
  box-shadow:0 10px 28px rgba(0,0,0,.14)}
.pickmenu .grp{font-size:10.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint);padding:4px 9px 6px}
.pickmenu form{margin:0}
.pickmenu button{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  font:inherit;font-size:13px;color:var(--ink2);padding:7px 9px;border-radius:7px}
.pickmenu button:hover{background:var(--line2)}
.pickmenu button[aria-current="true"]{background:var(--ink);color:var(--on-ink);font-weight:500}
.pickmenu button:focus-visible{outline:2px solid var(--ai);outline-offset:-2px}
/* The account menu is the avatar, so its summary is a name and a disc rather than one icon. */
.pick-user>summary{width:auto;height:auto;padding:4px 9px;color:inherit}
.usermenu{min-width:214px}
.usermenu .uhead{padding:6px 9px 9px;border-bottom:1px solid var(--line);margin-bottom:6px}
.usermenu .uhead b{display:block;font-size:13px;font-weight:600;color:var(--ink)}
.usermenu .uhead a{display:block;font-size:11.5px;color:var(--grey);text-decoration:none;
  margin-top:2px;overflow:hidden;text-overflow:ellipsis}
.usermenu .uhead a:hover{color:var(--ink);text-decoration:underline}
.usermenu .uitem{display:block;font-size:13px;color:var(--ink2);text-decoration:none;
  padding:7px 9px;border-radius:7px}
.usermenu .uitem:hover{background:var(--line2)}
.usermenu .uitem:focus-visible{outline:2px solid var(--ai);outline-offset:-2px}
/* The name can be long enough to crowd the icons on a phone; the icons are the part that
   still works without it, so it is the name that goes. */
@media (max-width:640px){.who span:not(.av){display:none}}
.av{width:28px;height:28px;border-radius:50%;background:var(--ink);color:var(--on-ink);
  display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600}
/* ----------------------------------------------------------------
   The workflow strip: the steps of the mode being read, laid out
   left to right under the header.

   The rail carries the five modes; this carries what is inside the
   one you are in. It scrolls inside itself rather than widening the
   page — a mode can hold six steps, and on a laptop that is wider
   than the column — which is why `ol` takes the overflow and not
   `body`. No counts and no ticks live here: a step is current, shut,
   or neither (§11c.10).
   ---------------------------------------------------------------- */
.flow{background:var(--panel);border-bottom:1px solid var(--line);padding:9px 30px}
.flow ol{list-style:none;margin:0;padding:0;display:flex;align-items:center;
  overflow-x:auto;scrollbar-width:thin}
.flow li{display:flex;align-items:center;flex:0 0 auto}
/* The connector is the ordering made visible; decorative, so it is not announced. */
.flow li+li::before{content:"";flex:0 0 auto;width:16px;height:1px;background:var(--line);margin:0 2px}
.flow .stbtn{background:none;border:0;cursor:pointer;white-space:nowrap;
  font:inherit;font-size:12.5px;color:var(--ink2);padding:6px 11px;border-radius:999px}
.flow .stbtn:hover{background:var(--line2)}
.flow .stbtn:focus-visible{outline:2px solid var(--ai);outline-offset:1px}
.flow .st.on .stbtn,.flow .stbtn[aria-current="step"]{background:var(--ink);color:var(--on-ink);font-weight:500}
.flow .st.shut .stbtn{color:var(--faint);cursor:not-allowed}
.flow .st.shut .stbtn:hover{background:none}
/* The way back into Build. Set apart from the steps because it is not one of them. */
.flow .st.back{margin-inline-start:auto;padding-inline-start:14px}
.flow .st.back::before{display:none}
.flow .st.back .stbtn{color:var(--grey)}
.flow .flowwhy{font-size:11.5px;color:var(--grey);line-height:1.5;margin:6px 0 2px;max-width:70ch}

main{padding:28px 30px 80px;max-width:1120px}
.view{display:none}
.view.on{display:block}

/* ---- common ---- */
.h{margin-bottom:22px}
.h h1{font-family:var(--serif);font-weight:400;font-size:26px;letter-spacing:-.012em;margin-bottom:5px}
.h p{color:var(--grey);font-size:13.5px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:4px;padding:20px 22px;margin-bottom:16px}
.card h3{font-size:13px;font-weight:600;margin-bottom:14px;letter-spacing:.01em}
.card h3 .sub{font-weight:400;color:var(--faint);margin-inline-start:8px;font-size:12px}
.g2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.g21{display:grid;grid-template-columns:1.55fr 1fr;gap:16px}
@media(max-width:900px){.g2,.g3,.g21{grid-template-columns:1fr}.app.on{grid-template-columns:1fr}.side{position:static;height:auto}}

.stat{font-family:var(--serif);font-size:30px;font-weight:400;line-height:1.1;letter-spacing:-.015em}
.stat i{font-style:normal;font-size:15px;color:var(--faint);font-family:var(--sans)}
.statlbl{font-size:12px;color:var(--grey);margin-top:4px}

.chip{display:inline-block;font-size:11px;font-weight:600;letter-spacing:.03em;padding:2px 8px;border-radius:2px;white-space:nowrap}
.chip.done{background:var(--ok-bg);color:var(--ok)}
.chip.now{background:var(--ai-bg);color:var(--ai)}
.chip.lock{background:var(--line2);color:var(--faint)}
.chip.flag{background:var(--human-bg);color:var(--human)}
.chip.ai{background:var(--ai-bg);color:var(--ai)}
.chip.hu{background:var(--human-bg);color:var(--human)}

table{width:100%;border-collapse:collapse;font-size:13.5px}
th{text-align:left;font-size:10.5px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--faint);padding:0 14px 9px 0;border-bottom:1px solid var(--line)}
td{padding:12px 14px 12px 0;border-bottom:1px solid var(--line2);vertical-align:middle}
tr:last-child td{border-bottom:0}
td .nm{font-weight:500}
td .sm{font-size:12px;color:var(--faint)}

/* evidence dots — progress as demonstrations, not time */
.dots{display:flex;gap:4px;align-items:center}
.dot{width:9px;height:9px;border-radius:50%;border:1px solid var(--line);background:var(--panel)}
.dot.f{background:var(--ok);border-color:var(--ok)}
.dot.p{background:var(--ai-bg);border-color:var(--ai)}
.dotn{font-size:11.5px;color:var(--grey);margin-inline-start:6px;white-space:nowrap}

.track{display:flex;gap:3px;margin:10px 0 6px}
.seg{flex:1;height:5px;background:var(--line2);border-radius:1px}
.seg.done{background:var(--ok)}
.seg.now{background:var(--ai)}
.tracklbl{display:flex;justify-content:space-between;font-size:11.5px;color:var(--faint)}

.li{display:flex;justify-content:space-between;gap:14px;align-items:flex-start;
  padding:11px 0;border-bottom:1px solid var(--line2)}
.li:last-child{border-bottom:0}
.li .t{font-size:13.5px;line-height:1.45}
.li .t b{font-weight:500}
.li .m{font-size:11.5px;color:var(--faint);white-space:nowrap;text-align:right}

.btn{font-size:13px;font-weight:500;background:var(--ink);color:var(--on-ink);border:0;padding:9px 16px;
  border-radius:3px;cursor:pointer}
.btn.g{background:none;color:var(--ink);border:1px solid var(--line)}
.btn.sm{font-size:12px;padding:6px 11px}
.btn:hover{opacity:.88}
.btn:focus-visible{outline:2px solid var(--ai);outline-offset:2px}
.row-actions{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap}

.note{font-size:12.5px;color:var(--grey);line-height:1.6;border-inline-start:2px solid var(--line);
  padding-inline-start:14px;margin-top:16px}
.unit{padding:16px 0;border-bottom:1px solid var(--line2);display:grid;
  grid-template-columns:34px 1fr 130px;gap:14px;align-items:start}
.unit:last-child{border-bottom:0}
.unum{width:26px;height:26px;border-radius:50%;border:1px solid var(--line);display:flex;
  align-items:center;justify-content:center;font-size:12px;color:var(--faint);margin-top:1px}
.unit.done .unum{background:var(--ok);border-color:var(--ok);color:var(--on-ink)}
.unit.now .unum{border-color:var(--ai);border-width:2px;color:var(--ai);font-weight:600}
.sec{display:grid;grid-template-columns:1fr 168px 118px;gap:14px;align-items:start;
  padding:14px 0;border-bottom:1px solid var(--line2)}
.sec:last-child{border-bottom:0}
.sec .nm2{font-size:14px;font-weight:500;margin-bottom:3px}
.sec .pv{font-size:12.5px;color:var(--grey);line-height:1.5}
.sec .from{font-size:11.5px;color:var(--faint)}
.crit{padding:16px 0;border-bottom:1px solid var(--line2)}
.crit:last-child{border-bottom:0}
.crit .ct{font-size:14px;font-weight:500;margin-bottom:4px}
.crit .cd{font-size:12.5px;color:var(--grey);line-height:1.5;margin-bottom:10px;max-width:62ch}
.lv{display:grid;grid-template-columns:repeat(4,1fr);gap:5px;margin-bottom:8px}
.lvb{border:1px solid var(--line);border-radius:3px;padding:8px 9px;font-size:11.5px;
  line-height:1.4;color:var(--grey);background:var(--panel)}
.lvb b{display:block;font-size:10.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin-bottom:4px}
.lvb.self{border-color:var(--ai);background:var(--ai-bg);color:var(--ai)}
.lvb.tch{border-color:var(--ink);background:var(--ink);color:var(--on-ink)}
.lvb.tch b,.lvb.self b{color:inherit;opacity:.75}
.lvb.both{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)}
.key{display:flex;gap:16px;flex-wrap:wrap;font-size:11.5px;color:var(--grey);margin-bottom:14px}
.key span{display:flex;align-items:center;gap:6px}
.sw{width:11px;height:11px;border-radius:2px;border:1px solid var(--line)}
@media(max-width:900px){.sec{grid-template-columns:1fr}.lv{grid-template-columns:1fr 1fr}}
.unit h4{font-family:var(--serif);font-weight:400;font-size:16.5px;margin-bottom:3px}
.unit p{font-size:12.5px;color:var(--grey);line-height:1.5}

/* ================================================================
   Astrolabe additions to the mockup's system.
   Everything above this line is the design language from the
   original mockup; everything below serves surfaces the mockup did
   not have, and follows its rules rather than inventing new ones.
   ================================================================ */

/* Anchoring is the system's central distinction, so it is a visual
   one: blue where AI may act, red where a person must. */
.anch{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;
  letter-spacing:.03em;padding:2px 8px;border-radius:2px;white-space:nowrap}
.anch.ai{background:var(--ai-bg);color:var(--ai);border:1px solid var(--ai-line)}
.anch.hu{background:var(--human-bg);color:var(--human);border:1px solid var(--human-line)}
.anch .dotmark{width:6px;height:6px;border-radius:50%;background:currentColor}

/* The same distinction said in words, where the two sides appear together. A badge is a
   reminder for somebody who already knows the scheme; this is for everybody else, and it
   sits at the top of the surface it governs rather than in its heading. The badges are a
   column of their own so the two chips align and the sentences start on one edge — read
   down, it answers "who does what" without the reader decoding a colour first. */
.handoff{margin:0 0 18px;padding:13px 15px;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--line2)}
.handoff .hh{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--grey);margin-bottom:10px}
.handoff .hrow{display:grid;grid-template-columns:max-content 1fr;gap:12px;align-items:start}
.handoff .hrow + .hrow{margin-top:9px}
.handoff .hrow p{font-size:12.5px;line-height:1.6;color:var(--ink2)}
/* Under about 560px the chip and its sentence stop fitting side by side, and a 90px column
   of wrapped prose is worse than the stack. */
@media (max-width:560px){
  .handoff .hrow{grid-template-columns:1fr;gap:5px}
}

/* A panel the educator owns. The left rule is the visual promise
   that nothing in here was written for them. */
.mine{border-inline-start:3px solid var(--human);padding-inline-start:16px}
.theirs{border-inline-start:3px solid var(--ai);padding-inline-start:16px}

.field textarea{width:100%;padding:11px 13px;border:1px solid var(--line);background:var(--panel);
  font-family:inherit;font-size:14px;line-height:1.6;color:var(--ink);border-radius:3px;
  min-height:130px;resize:vertical}
.field textarea:focus{outline:2px solid var(--human);outline-offset:-1px;border-color:transparent}
.field .hint{font-size:12px;color:var(--faint);margin-top:5px;line-height:1.5}
/* Not a hint. It says which discipline pack is specialising the page and how far that is from
 * what the educator actually teaches, so it has to read as a statement about their situation
 * rather than as guidance about the control above it. Same ink as the AI disclosures. */
.field .hint.borrowed{color:var(--ai);background:var(--ai-bg);border:1px solid var(--ai-line);
  border-radius:3px;padding:8px 10px;margin-top:7px}
.field select{width:100%;padding:10px 12px;border:1px solid var(--line);background:var(--panel);
  font-family:inherit;font-size:14px;border-radius:3px}

fieldset{border:0;padding:0;margin:0 0 18px}
legend{font-size:13px;font-weight:600;margin-bottom:10px;padding:0}

.opt{display:flex;gap:10px;align-items:flex-start;padding:11px 13px;border:1px solid var(--line);
  border-radius:3px;margin-bottom:8px;background:var(--panel);cursor:pointer}
.opt:hover{border-color:var(--ink2)}
/* The control keeps the browser's own focus ring, but a checkbox is small and the thing the
 * educator is reading is the row around it, so the row answers to focus the way it answers to
 * hover. `.field input:focus` used to do this by accident, from a rule about text boxes. */
.opt:focus-within{border-color:var(--ai)}
.opt input{margin-top:3px;flex:none}
.opt .lb{font-size:13.5px;line-height:1.5}
.opt.checked{border-color:var(--ai);background:var(--ai-bg)}
.opt .why{margin-top:9px}
.opt .why textarea{min-height:64px;font-size:13px}

/* The inherited-tier picker: the register's own nesting, not a list.
 *
 * Indentation is the whole point — it is what shows that these approaches sit under a
 * question rather than beside each other — so each level gets a rule down its left edge and
 * the leaf options sit inside it. Nothing here is a metric: `.tn` counts approaches in a
 * branch, never anything about a person.
 */
.tierpick{border:1px solid var(--line);border-radius:3px;padding:14px;background:var(--bg)}
.tierpick > legend{padding:0 6px;margin-inline-start:-6px}
/* A split is one descriptor question with its two answers under it — the question named once,
 * because it is not a question the educator answers but the axis the approaches differ on. */
.tsplit{margin-bottom:8px}
.tsplit > .tq{font-size:13px;line-height:1.5;margin:0 0 7px}
.tsplit > .tq b{display:block;font-weight:600}
.tsplit > .tq span{color:var(--ink2);font-size:12.5px}
.tnode{margin-bottom:6px}
.tnode > summary{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:baseline;cursor:pointer;
  padding:9px 11px;border:1px solid var(--line);border-radius:3px;background:var(--panel);
  font-size:13px;list-style:none}
.tnode > summary::-webkit-details-marker{display:none}
.tnode > summary::before{content:"▸";flex:none;color:var(--faint);font-size:11px}
.tnode[open] > summary::before{content:"▾"}
.tnode > summary:hover{border-color:var(--ink2)}
.tnode .ta{font-weight:500}
.tnode .tn{color:var(--faint);font-size:12px;margin-inline-start:auto}
/* Each level steps in and carries a rule, so depth is legible without counting. */
.tnode > .tsplit,.tnode > .tleaf{margin-inline-start:11px;padding-inline-start:12px;border-inline-start:1px solid var(--line);
  margin-top:8px}
.tleaf .opt{margin-bottom:6px}
.tleaf .hint{font-size:12px;color:var(--faint);margin:0 0 8px;line-height:1.5}
.opt .gl{display:block;color:var(--ink2);font-size:12.5px;margin-top:3px}
/* Set apart, because it is a different kind of answer: not one of the approaches, but a
 * report that the question was never settled where this educator teaches. */
.opt.unstated{margin-top:12px;border-style:dashed}

/* The sort. No hints, no definitions on hover — see §8b. */
.sortgrid{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin-top:16px}
@media(max-width:900px){.sortgrid{grid-template-columns:1fr}}
.bucket{border:1px dashed var(--line);border-radius:4px;padding:12px;min-height:150px;background:var(--panel)}
.bucket h4{font-size:11.5px;font-weight:600;letter-spacing:.04em;color:var(--ink2);margin-bottom:10px;line-height:1.35}
.chiplbl{display:block;width:100%;text-align:left;font-size:12.5px;padding:7px 9px;margin-bottom:6px;
  border:1px solid var(--line);border-radius:3px;background:var(--bg);cursor:pointer}
.chiplbl.on{background:var(--ink);color:var(--on-ink);border-color:var(--ink)}

.pool{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0}
.pool button{font-size:13px;padding:8px 12px;border:1px solid var(--line);background:var(--panel);
  border-radius:3px;cursor:pointer}
.pool button[aria-pressed="true"]{background:var(--ink);color:var(--on-ink);border-color:var(--ink)}

/* Gaps: two values and the distance between them, never a score. */
.gap{display:grid;grid-template-columns:150px 1fr 90px;gap:14px;align-items:center;
  padding:14px 0;border-bottom:1px solid var(--line2)}
.gap:last-child{border-bottom:0}
@media(max-width:900px){.gap{grid-template-columns:1fr}}
.scale{position:relative;height:26px}
.scale .rail{position:absolute;top:12px;left:0;right:0;height:2px;background:var(--line)}
.scale .mk{position:absolute;top:6px;width:14px;height:14px;border-radius:50%;transform:translateX(-7px)}
.scale .mk.esp{background:var(--human)}
.scale .mk.ena{background:var(--ai)}
.scale .span{position:absolute;top:12px;height:2px;background:var(--ink2)}
.poles{display:flex;justify-content:space-between;font-size:11px;color:var(--faint);margin-top:2px}

.quote{font-family:var(--serif);font-size:14px;line-height:1.6;color:var(--ink2);
  border-inline-start:2px solid var(--line);padding:2px 0 2px 14px;margin:10px 0}
.quote cite{display:block;font-family:var(--sans);font-style:normal;font-size:11.5px;
  color:var(--faint);margin-top:5px}

.dispute{background:var(--bg);border:1px solid var(--line);border-radius:4px;padding:14px 16px;margin-top:12px}
.dispute h5{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin:0 0 8px}
.dispute p{font-size:13px;line-height:1.6;color:var(--ink2)}
.dispute ul{margin:8px 0 0;padding-inline-start:18px;font-size:12px;color:var(--grey);line-height:1.6}

/* Layer 4 — a finding of the research literature, as the register holds it.
 *
 * The statement leads, because the principle is the thing being learnt; the strength chip sits
 * above it rather than inside the sentence, so a conditional finding cannot be skim-read as a
 * settled one. Citations are small but never hidden: an educator who wants to go and read
 * Sweller should be able to, and a claim whose basis is folded away is indistinguishable from
 * an assertion.
 */
.finding{border:1px solid var(--line);border-radius:8px;background:var(--panel);
  padding:18px 20px;margin-bottom:14px}
.fhead{display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin-bottom:10px}
.ftier{font-size:11px;color:var(--faint);letter-spacing:.04em;text-transform:uppercase}
.fstatement{font-size:15px;line-height:1.6;color:var(--ink);margin:0 0 14px;font-weight:500}
.finding h5{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin:0 0 6px}
.fwhy,.fbounds,.fbasis,.fpractice{margin-top:12px}
.fwhy ul,.fbounds ul,.fbasis ul{margin:0;padding-inline-start:18px;line-height:1.6}
.fwhy ul{font-size:13px;color:var(--ink2)}
.fbounds ul{font-size:12.5px;color:var(--grey)}
.fbasis ul{font-size:12px;color:var(--grey)}
.fbasis .doi{color:var(--faint)}
.fpractice a{margin-inline-end:8px;display:inline-block;margin-bottom:6px}
/* Strength is a property of the evidence, never of the educator — see the no-ranking rule. */
.chip.strong{background:var(--ok-bg);color:var(--ok)}
.chip.conditional{background:var(--ai-bg);color:var(--ai)}
.chip.contested{background:var(--human-bg);color:var(--human)}
.chip.rejected{background:var(--line2);color:var(--faint)}

.refusal{border:1px solid var(--human-line);background:var(--human-bg);border-radius:4px;padding:18px 20px;margin-bottom:16px}
.refusal h3{font-size:13px;margin-bottom:12px;color:var(--human)}
.refusal ol{margin:0;padding-inline-start:20px;font-size:13.5px;line-height:1.65;color:var(--ink2)}
.refusal li{margin-bottom:8px}
.refusal .why{font-size:12.5px;color:var(--grey);margin-top:12px;line-height:1.6}

.dual{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--line);border-radius:4px;overflow:hidden}
@media(max-width:700px){.dual{grid-template-columns:1fr}}
.dual > div{padding:16px 18px}
.dual .l{background:var(--ai-bg);border-inline-end:1px solid var(--line)}
.dual .r{background:var(--human-bg)}
.dual h4{font-family:var(--serif);font-weight:400;font-size:19px;margin-bottom:4px}
.dual .k{font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);margin-bottom:10px}
.dual p{font-size:12.5px;line-height:1.6;color:var(--ink2)}

.tierhead{display:flex;align-items:baseline;gap:10px;margin:26px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.tierhead h3{font-family:var(--serif);font-weight:400;font-size:18px}
.tierhead span{font-size:12.5px;color:var(--grey)}

.out{padding:13px 0;border-bottom:1px solid var(--line2)}
.out:last-child{border-bottom:0}
.out .nm3{font-size:14px;font-weight:500}
.out .rs{font-size:12.5px;color:var(--grey);line-height:1.6;margin-top:4px;max-width:74ch}
.out .cite{font-size:11.5px;color:var(--faint);margin-top:6px;line-height:1.5}

/* ---- The separating question (Layer 3) -------------------------------------
 * Its own block, because it was borrowing two others that were built for
 * something else and neither survived the loan.
 *
 * `.unit` is the mini course's grid — 34px number, 1fr body, 130px actions —
 * and this block has four children, so the question wrapped inside the 34px
 * number column and one side of the split fell into the next row. `.li` is a
 * label with its value: `.m` is 11.5px, --faint, right-aligned and `nowrap`,
 * which is metadata styling, and here the label lists ARE the content. Five
 * Tier 2 names cannot be a nowrap right rail.
 *
 * The two halves are deliberately identical — same border, same weight, same
 * order as `separatingQuestions` returns them. The card says in as many words
 * that neither side is the right one, so any asymmetry here (a fill, a rule, a
 * first position that reads as first choice) would contradict the copy in the
 * one register an educator reads faster than prose. Same argument as the five
 * identical primary buttons below it.
 */
.sep{padding-bottom:2px}
.sep + .sep{margin-top:18px;padding-top:18px;border-top:1px solid var(--line2)}
/* Dimension, then the question that dimension asks, then the question the halves below
   actually answer. The middle one is the substance and gets the serif; the last one is
   operative and sits against the halves, whose two keys are its two answers. */
.sep .dsc{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin-bottom:5px}
.sep .q{font-family:var(--serif);font-weight:400;font-size:15.5px;line-height:1.45}
.sep .ask{font-size:13px;font-weight:500;color:var(--ink2);line-height:1.5;margin-top:7px}
.sep .halves{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px}
.sep .half{border:1px solid var(--line2);border-radius:3px;padding:10px 12px;background:var(--bg)}
.sep .half .k{font-size:10.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin-bottom:6px}
.sep .half .ls{font-size:13px;line-height:1.65;color:var(--ink2)}
/* Below this the two halves are taller than they are wide and the pairing stops reading;
   stacked, the uppercase keys still carry which side is which. */
@media(max-width:620px){.sep .halves{grid-template-columns:1fr}}

.led{width:100%;border-collapse:collapse;font-size:12.5px}
.led th{font-size:10px}
.led td{padding:10px 12px 10px 0;vertical-align:top}
.led tr.hu td{background:var(--human-bg)}

.sse{font-size:13.5px;line-height:1.6;min-height:22px}
.sse.pending::after{content:'▌';animation:blink 1s steps(2) infinite;color:var(--faint)}
@keyframes blink{50%{opacity:0}}
@media(prefers-reduced-motion:reduce){.sse.pending::after{animation:none}}

.teaser{max-width:620px;margin:0 auto;padding:60px 20px}
.teaser .beat{font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);margin-bottom:18px}
.teaser h2{font-family:var(--serif);font-weight:400;font-size:23px;line-height:1.4;margin-bottom:14px;letter-spacing:-.01em}
.teaser .setup{font-size:15px;line-height:1.65;color:var(--ink2);margin-bottom:22px}
.teaser .ask{font-size:14px;font-weight:500;margin-bottom:14px}

.err{border:1px solid var(--human-line);background:var(--human-bg);color:var(--human);
  border-radius:4px;padding:14px 16px;font-size:13.5px;line-height:1.6;margin-bottom:16px}
.err b{display:block;margin-bottom:4px}
.ok{border:1px solid var(--ok);background:var(--ok-bg);color:var(--ok);
  border-radius:4px;padding:12px 15px;font-size:13.5px;margin-bottom:16px}

a{color:var(--ai)}
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{
  outline:2px solid var(--ai);outline-offset:2px}
.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;z-index:99;background:var(--panel);padding:10px 14px;border:1px solid var(--ink)}

/* Role switcher — shown only for an account the allowlists entitle to more than one
   view. It is a lens over existing entitlement, never a way to acquire a role. */
.switcher{margin-top:18px;padding:0 10px}
.switcher .grp{padding:0 10px 6px}
.switcher form{margin:0}
.switcher button{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  font-size:13px;color:var(--ink2);padding:7px 10px;border-radius:3px;font-family:inherit}
.switcher button:hover{background:var(--line2)}
.switcher button[aria-current="true"]{background:var(--ai-bg);color:var(--ai);font-weight:500}

/* Language switcher. Same furniture as the role switcher inside the app chrome, so the two
   read as one column of settings rather than two inventions. */
.langpick{margin-top:18px;padding:0 10px}
.langpick .grp{padding:0 10px 6px}
.langpick form{margin:0}
.langpick button{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  font-size:13px;color:var(--ink2);padding:7px 10px;border-radius:3px;font-family:inherit}
.langpick button:hover{background:var(--line2)}
.langpick button[aria-current="true"]{background:var(--ink);color:var(--on-ink);font-weight:500}

/* On a signed-out page there is no sidebar to put it in, and the landing page, the split
   sign-in and the teaser each carry a different header — so it sits in the one corner all
   three leave empty. Somebody who arrived in a language they cannot read needs it before
   they read anything else, which is why it is on screen rather than behind a menu. */
.langbar{position:fixed;bottom:16px;right:16px;z-index:50;display:flex;align-items:center;gap:2px;
  background:var(--panel);border:1px solid var(--line);border-radius:3px;padding:4px;
  box-shadow:var(--shadow)}
.langbar .grp{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);padding:0 8px}
.langbar form{margin:0}
.langbar button{background:none;border:0;cursor:pointer;font-family:inherit;font-size:12.5px;
  color:var(--ink2);padding:5px 9px;border-radius:2px;white-space:nowrap}
.langbar button:hover{background:var(--line2)}
.langbar button[aria-current="true"]{background:var(--ink);color:var(--on-ink);font-weight:500}
@media (max-width:640px){
  .langbar{bottom:8px;right:8px;left:8px;justify-content:center;flex-wrap:wrap}
}

/* ================================================================
   Landing, sign-in and dashboard chrome.
   Same tokens, same type scale, same restraint as everything above.
   ================================================================ */

/* ---- landing ---- */
.lp{background:var(--bg)}
.lp-nav{position:sticky;top:0;z-index:20;background:var(--veil);
  backdrop-filter:blur(8px);border-bottom:1px solid var(--line)}
.lp-nav-in{max-width:1080px;margin:0 auto;padding:12px 28px;display:flex;align-items:center;gap:26px}
.lp-mark{font-family:var(--serif);font-weight:400;font-size:18px;letter-spacing:-.01em;
  color:var(--ink);text-decoration:none;white-space:nowrap}
.lp-mark i{font-style:normal;color:var(--faint);font-size:14px;margin-inline-start:7px;letter-spacing:.14em}
.lp-nav nav{display:flex;gap:20px;flex:1}
.lp-nav nav a{font-size:12.5px;color:var(--grey);text-decoration:none}
.lp-nav nav a:hover{color:var(--ink)}
@media(max-width:820px){.lp-nav nav{display:none}}

.lp-wrap{max-width:1080px;margin:0 auto;padding:0 28px}
.lp-hero{display:grid;grid-template-columns:1.12fr .88fr;gap:44px;align-items:center;
  padding:76px 0 68px}
@media(max-width:900px){.lp-hero{grid-template-columns:1fr;gap:30px;padding:48px 0 40px}}
.lp-eyebrow{font-size:11px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  color:var(--faint);margin-bottom:20px;line-height:1.6}
.lp-hero h1{font-family:var(--serif);font-weight:300;font-size:56px;line-height:1.04;
  letter-spacing:-.028em;margin-bottom:10px}
.lp-hero h1 i{font-style:normal;font-size:26px;color:var(--faint);letter-spacing:.16em;
  margin-inline-start:14px;vertical-align:.32em}
@media(max-width:900px){.lp-hero h1{font-size:40px}.lp-hero h1 i{font-size:19px;margin-inline-start:9px}}
.lp-tagline{font-family:var(--serif);font-size:20px;line-height:1.45;color:var(--ink2);margin-bottom:22px}
.lp-lead{font-size:15px;line-height:1.72;color:var(--ink2);max-width:52ch;margin-bottom:14px}
.lp-lead + .lp-lead{color:var(--grey);font-size:14px}
.lp-cta{display:flex;gap:10px;flex-wrap:wrap;margin-top:26px}
.lp-cta .btn{padding:12px 22px;font-size:13.5px}
.lp-micro{font-size:12.5px;color:var(--faint);margin-top:14px;line-height:1.6;max-width:46ch}

.lp-art{display:flex;justify-content:center}
.lp-art svg{width:100%;max-width:340px;height:auto}
@media(max-width:900px){.lp-art{display:none}}

.lp-band{border-top:1px solid var(--line);padding:64px 0}
.lp-band.alt{background:var(--panel)}
@media(max-width:900px){.lp-band{padding:44px 0}}
.lp-sec{max-width:1080px;margin:0 auto;padding:0 28px}
.lp-sec-head{max-width:60ch;margin-bottom:30px}
.lp-sec-head .k{font-size:11px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  color:var(--faint);margin-bottom:12px}
.lp-sec-head h2{font-family:var(--serif);font-weight:400;font-size:29px;line-height:1.24;
  letter-spacing:-.015em;margin-bottom:10px}
@media(max-width:900px){.lp-sec-head h2{font-size:24px}}
.lp-sec-head p{font-size:14.5px;line-height:1.7;color:var(--ink2)}

/* three role cards */
.lp-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
@media(max-width:900px){.lp-cards{grid-template-columns:1fr}}
.rolecard{background:var(--panel);border:1px solid var(--line);border-radius:4px;
  padding:22px 22px 20px;display:flex;flex-direction:column}
.lp-band.alt .rolecard{background:var(--bg)}
.rolecard .rk{font-size:10.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint);margin-bottom:10px}
.rolecard h3{font-family:var(--serif);font-weight:400;font-size:20px;margin-bottom:8px}
.rolecard p{font-size:13.5px;line-height:1.65;color:var(--ink2);margin-bottom:14px}
.rolecard ul{margin:0 0 18px;padding-inline-start:17px;font-size:13px;line-height:1.75;color:var(--grey)}
.rolecard .foot{margin-top:auto;font-size:12.5px}

/* the numbered refusals */
.lp-refuse{display:grid;grid-template-columns:1fr 1fr;gap:0 34px}
@media(max-width:900px){.lp-refuse{grid-template-columns:1fr}}
.refline{display:grid;grid-template-columns:30px 1fr;gap:14px;padding:18px 0;
  border-bottom:1px solid var(--line)}
.refline .n{font-family:var(--serif);font-size:19px;color:var(--faint);line-height:1.3}
.refline p{font-size:13.5px;line-height:1.65;color:var(--ink2)}
.refline .where{font-size:11.5px;color:var(--faint);margin-top:6px;font-family:var(--sans)}

/* live numbers, computed at render so they cannot drift */
.lp-facts{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
@media(max-width:900px){.lp-facts{grid-template-columns:1fr 1fr}}
.fact{border-inline-start:2px solid var(--line);padding-inline-start:16px}
.fact .v{font-family:var(--serif);font-size:32px;font-weight:300;line-height:1.1;letter-spacing:-.02em}
.fact .l{font-size:12.5px;color:var(--grey);margin-top:5px;line-height:1.5}

.lp-foot{border-top:1px solid var(--line);background:var(--panel);padding:34px 0 46px;
  font-size:12.5px;color:var(--faint);line-height:1.7}
.lp-foot .lp-sec{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
.lp-foot a{color:var(--grey);text-decoration:none;margin-inline-end:16px}
.lp-foot a:hover{color:var(--ink)}

/* teaser beat, on the landing page */
.beatcard{background:var(--panel);border:1px solid var(--line);border-radius:4px;padding:22px 24px}
.lp-band.alt .beatcard{background:var(--bg)}
.beatcard .beat{font-size:10.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint);margin-bottom:12px}
.beatcard h3{font-family:var(--serif);font-weight:400;font-size:17px;line-height:1.45;margin-bottom:10px}
.beatcard .ask{font-size:13px;font-weight:500;margin-bottom:12px;color:var(--ink2)}
.beatcard .opt{padding:9px 11px;margin-bottom:6px}
.beatcard .opt .lb{font-size:12.5px}

/* ---- sign in ---- */
.auth{display:grid;grid-template-columns:1fr 1fr;min-height:100vh}
@media(max-width:860px){.auth{grid-template-columns:1fr}}
.auth-aside{background:var(--ink);color:var(--on-ink);padding:48px 46px;display:flex;
  flex-direction:column;justify-content:center}
@media(max-width:860px){.auth-aside{padding:36px 26px}}
.auth-aside .brand{font-family:var(--serif);font-weight:300;font-size:34px;letter-spacing:-.02em;
  margin-bottom:2px;color:var(--on-ink)}
.auth-aside .cn{font-family:var(--serif);font-size:17px;letter-spacing:.2em;
  color:var(--on-ink-faint);margin-bottom:18px}
.auth-aside .tag{font-family:var(--serif);font-size:17px;line-height:1.5;
  color:var(--on-ink-soft);margin-bottom:26px;max-width:34ch}
.auth-aside ul{list-style:none;margin:0;padding:0;max-width:38ch}
.auth-aside li{font-size:13px;line-height:1.6;color:var(--on-ink-mute);
  padding:11px 0;border-top:1px solid var(--on-ink-line)}
.auth-aside li b{display:block;color:var(--on-ink);font-weight:500;font-size:13px;margin-bottom:2px}
.auth-aside .inst{font-size:11.5px;color:var(--on-ink-dim);margin-top:28px;line-height:1.6;max-width:38ch}
.auth-aside a{color:var(--on-ink-link)}

.auth-main{display:flex;align-items:center;justify-content:center;padding:48px 28px;background:var(--bg)}
.auth-form{width:100%;max-width:392px}
.auth-form h1{font-family:var(--serif);font-weight:400;font-size:26px;letter-spacing:-.012em;margin-bottom:6px}
.auth-form .sub{font-size:13.5px;color:var(--grey);line-height:1.6;margin-bottom:26px}
.auth-form .or{display:flex;align-items:center;gap:12px;font-size:11.5px;color:var(--faint);margin:18px 0}
.auth-form .or::before,.auth-form .or::after{content:'';flex:1;height:1px;background:var(--line)}
.auth-form .foot{margin-top:24px;padding-top:18px;border-top:1px solid var(--line);
  font-size:12.5px;color:var(--faint);line-height:1.7}

/* role picker — a card each, so the choice explains itself */
.rolepick{display:grid;gap:8px;margin-bottom:6px}
.rolepick label{display:grid;grid-template-columns:18px 1fr;gap:11px;align-items:start;
  border:1px solid var(--line);border-radius:3px;padding:12px 14px;background:var(--panel);cursor:pointer}
.rolepick label:hover{border-color:var(--ink2)}
.rolepick input{margin-top:3px}
.rolepick .rn{font-size:13.5px;font-weight:500;line-height:1.4}
.rolepick .rd{font-size:12px;color:var(--grey);line-height:1.5;margin-top:2px}
.rolepick label:has(input:checked){border-color:var(--ink);background:var(--panel);
  box-shadow:inset 0 0 0 1px var(--ink)}

/* ---- dashboard chrome ---- */
.dashhead{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;
  flex-wrap:wrap;margin-bottom:22px;padding-bottom:18px;border-bottom:1px solid var(--line)}
.dashhead .k{font-size:10.5px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  color:var(--faint);margin-bottom:7px}
.dashhead h1{font-family:var(--serif);font-weight:400;font-size:27px;letter-spacing:-.014em;
  line-height:1.2;margin-bottom:6px}
.dashhead p{font-size:13.5px;color:var(--grey);max-width:64ch;line-height:1.6}
.dashhead .meta{display:flex;gap:8px;flex-wrap:wrap;align-items:center}

.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:14px;margin-bottom:16px}
.tile{background:var(--panel);border:1px solid var(--line);border-radius:4px;padding:16px 18px}
.tile .tl{font-size:10.5px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--faint);margin-bottom:9px}
.tile .tv{font-family:var(--serif);font-size:27px;font-weight:400;line-height:1.15;
  letter-spacing:-.015em;word-break:break-word}
.tile .tv.sm{font-size:19px}
.tile .tf{font-size:12px;color:var(--grey);margin-top:6px;line-height:1.5}
.tile.warn{border-color:var(--human-line);background:var(--human-bg)}
.tile.warn .tv{color:var(--human)}

/* the single next act. Deliberately the loudest thing on the page. */
.focus{background:var(--panel);border:1px solid var(--line);border-inline-start:3px solid var(--human);
  border-radius:4px;padding:22px 24px;margin-bottom:16px}
.focus .k{font-size:10.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--human);margin-bottom:11px;display:flex;justify-content:space-between;gap:12px}
.focus .k span{color:var(--faint);font-weight:400;letter-spacing:0;text-transform:none;font-size:11.5px}
.focus h2{font-family:var(--serif);font-weight:400;font-size:21px;line-height:1.42;margin-bottom:10px}
.focus .why{font-size:13px;line-height:1.65;color:var(--grey);max-width:70ch}
.focus .why b{color:var(--ink2);font-weight:500}

/* stage state. Names and states, never a count and never a bar (§12e.5). */
.states{display:flex;gap:8px;flex-wrap:wrap;margin:2px 0 4px}
.state{border:1px solid var(--line);border-radius:3px;padding:9px 13px;background:var(--panel);
  flex:1 1 120px;min-width:120px}
.state .sn{font-size:13px;font-weight:500;margin-bottom:4px}
.state .ss{font-size:11px;font-weight:600;letter-spacing:.04em;color:var(--faint)}
.state.cleared{border-color:var(--ok);background:var(--ok-bg)}
.state.cleared .ss{color:var(--ok)}
.state.open{border-color:var(--ai);background:var(--ai-bg)}
.state.open .sn,.state.open .ss{color:var(--ai)}
.state.shut{opacity:.62}

.quick{display:flex;gap:8px;flex-wrap:wrap}
.quick a{text-decoration:none}

/* The mini course's published rubric. A grid, because the point is that a criterion and its
   levels are read together — the educator has to see what the next level would look like. */
.rub{width:100%;border-collapse:collapse;font-size:12.5px;margin-top:12px;min-width:640px}
.rub th,.rub td{border:1px solid var(--line);padding:9px 11px;text-align:left;vertical-align:top}
.rub thead th{background:var(--line2);font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink2);font-weight:600;white-space:nowrap}
.rub tbody th{background:var(--panel);width:26%;font-weight:400}
.rub tbody th b{display:block;font-weight:600;font-size:13px;margin-bottom:4px}
.rub tbody th span{display:block;color:var(--ink2);margin-bottom:5px}
.rub tbody th i{display:block;font-style:normal;font-size:11.5px;color:var(--faint);line-height:1.5}
.rub td{color:var(--ink2);line-height:1.55}

/* ================================================================
   Themes.

   Each is a block of tokens, not a second stylesheet: everything
   above already reads through them, so a theme changes colour and
   depth without touching a single layout rule.

   `paper` is the default and is the base :root above, restated here
   so that an explicit choice and the absence of one render the same.
   ================================================================ */

[data-theme="dark"]{
  --bg:#16150F; --panel:#1F1E17; --ink:#F3F0E8; --ink2:#D3CDC0; --grey:#A8A093; --faint:#948C7E;
  --line:#34322B; --line2:#272520;
  --ai:#A6BEEC; --ai-bg:#1A2132; --ai-line:#3A4767;
  --human:#EDACA6; --human-bg:#2C1B1A; --human-line:#5E3A37;
  --ok:#8FD0B1; --ok-bg:#152720;
  /* --ink is now the LIGHT colour, so what sits on it has to be dark. */
  --on-ink:#16150F;
  --on-ink-soft:rgba(22,21,15,.86); --on-ink-mute:rgba(22,21,15,.74);
  --on-ink-faint:rgba(22,21,15,.55); --on-ink-dim:rgba(22,21,15,.45);
  --on-ink-line:rgba(22,21,15,.16); --on-ink-link:rgba(22,21,15,.66);
  --shadow:0 1px 3px rgba(0,0,0,.55);
  --veil:rgba(22,21,15,.93);
  color-scheme:dark;
}

/* Maximum legibility, and nothing else asked to be looked at: no tints behind text, no
   shadows, no translucency, every border drawn. Text pairs here are 12:1 or better —
   `npm test` computes them rather than trusting the eye. */
[data-theme="contrast"]{
  --bg:#FFFFFF; --panel:#FFFFFF; --ink:#000000; --ink2:#000000; --grey:#1C1C1C; --faint:#333333;
  --line:#000000; --line2:#6B6B6B;
  --ai:#00327F; --ai-bg:#FFFFFF; --ai-line:#00327F;
  --human:#8A0000; --human-bg:#FFFFFF; --human-line:#8A0000;
  --ok:#00452A; --ok-bg:#FFFFFF;
  --on-ink:#FFFFFF;
  --on-ink-soft:#FFFFFF; --on-ink-mute:#FFFFFF; --on-ink-faint:#E8E8E8;
  --on-ink-dim:#E8E8E8; --on-ink-line:rgba(255,255,255,.5); --on-ink-link:#FFFFFF;
  --shadow:none;
  --veil:#FFFFFF;
  --glass:none;
  --focus:3px;
  --border:2px;
}
/* A tint carries the meaning in the other themes; here the border has to carry it. */
[data-theme="contrast"] .chip,
[data-theme="contrast"] .anch{border:var(--border) solid currentColor}
[data-theme="contrast"] .card,
[data-theme="contrast"] .opt,
[data-theme="contrast"] .lvb,
/* --bg and --panel are both white here, so the half's tint vanishes and its border is the only
   thing left saying where one side of the split ends and the other begins. */
[data-theme="contrast"] .sep .half,
[data-theme="contrast"] .field input,
[data-theme="contrast"] .field textarea,
[data-theme="contrast"] .field select{border-width:var(--border)}
[data-theme="contrast"] .btn.g{border-width:var(--border)}
[data-theme="contrast"] .lp-nav,
[data-theme="contrast"] .langbar,
[data-theme="contrast"] .pickmenu{backdrop-filter:none}
/* Colour alone never distinguishes a link from its sentence (WCAG 1.4.1). */
[data-theme="contrast"] a{text-decoration:underline}
[data-theme="contrast"] :focus-visible{outline:var(--focus) solid var(--ink);outline-offset:2px}

/* Liquid glass — translucent panels over a lit background. The blur is a token so that the
   accessibility guards below can switch it off in one place rather than per surface. */
[data-theme="glass"]{
  --bg:#EDEBF2; --panel:rgba(255,255,255,.58); --ink:#171520; --ink2:#413D52; --grey:#6B6678;
  --faint:#948FA3;
  --line:rgba(255,255,255,.75); --line2:rgba(120,110,150,.16);
  --ai:#2E4A8C; --ai-bg:rgba(214,225,247,.62); --ai-line:rgba(120,150,220,.45);
  --human:#8F2F3F; --human-bg:rgba(250,228,230,.62); --human-line:rgba(200,140,150,.45);
  --ok:#26624A; --ok-bg:rgba(214,240,228,.62);
  --shadow:0 6px 24px rgba(40,30,70,.13),0 1px 2px rgba(40,30,70,.10);
  --veil:rgba(237,235,242,.62);
  --glass:saturate(1.6) blur(16px);
  --bg-image:
    radial-gradient(ellipse 70% 60% at 8% -8%,rgba(150,190,255,.55),transparent 60%),
    radial-gradient(ellipse 60% 55% at 98% 8%,rgba(255,190,215,.48),transparent 62%),
    radial-gradient(ellipse 80% 60% at 50% 108%,rgba(180,235,225,.50),transparent 60%);
}
[data-theme="glass"] .card,
[data-theme="glass"] .side,
[data-theme="glass"] .top,
[data-theme="glass"] .pickmenu,
[data-theme="glass"] .langbar,
[data-theme="glass"] .lp-nav,
[data-theme="glass"] .opt,
/* It floats over the pool the way .pickmenu floats over the page, and --panel is
   translucent here — without the blur the gloss is read through whatever label is behind it. */
[data-theme="glass"] .whatisbody,
[data-theme="glass"] .lvb{backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass)}
[data-theme="glass"] .card{box-shadow:var(--shadow);border-radius:12px}
[data-theme="glass"] .side{border-inline-end-color:var(--line)}
[data-theme="glass"] .btn{border-radius:8px}
/* A ghost button IS its outline, and --line is white here — on a translucent white card that
   outline disappears and the control reads as inert text rather than something you can press.
   Every other theme's --line is opaque and contrasting, so this is the one place it fails.
   The theme's own answer for inputs and .opt is to give the control a surface to sit on; a
   button needs the edge as well, so it gets both. */
[data-theme="glass"] .btn.g{background:rgba(255,255,255,.55);border-color:rgba(90,80,120,.30)}
[data-theme="glass"] .btn.g:hover{border-color:rgba(90,80,120,.55)}
[data-theme="glass"] .opt,
[data-theme="glass"] .field input,
[data-theme="glass"] .field textarea,
[data-theme="glass"] .field select{border-radius:8px;background:var(--panel)}

/* The background is painted on <body> so the blurred panels have something to refract. */
body{background-image:var(--bg-image);background-attachment:fixed}

/* ---- accessibility guards ----------------------------------------------------------
   A theme is a preference; these are not. Anyone who has asked their system for less
   transparency or more contrast gets it, whichever theme is selected — a decorative blur
   is never worth overriding a stated access need. */
@media (prefers-reduced-transparency: reduce){
  [data-theme="glass"]{
    --panel:#FFFFFF; --line:#DEDAE6; --line2:#EDEAF2;
    --ai-bg:#E7EDFA; --human-bg:#FAEDEF; --ok-bg:#E6F3EC; --veil:#EDEBF2;
    --glass:none; --bg-image:none;
  }
}
@media (prefers-contrast: more){
  [data-theme="glass"]{
    --panel:#FFFFFF; --ink:#000000; --ink2:#1C1C1C; --grey:#333333;
    --line:#767676; --line2:#767676; --glass:none; --bg-image:none;
  }
  [data-theme="paper"],[data-theme="system"]{--grey:#5C564D; --faint:#6E675C; --line:#B8B2A6;}
}
@media (prefers-reduced-motion: reduce){
  *{animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
}

/* `system` follows the operating system, so somebody who has already made the choice once
   does not have to make it again here. */
@media (prefers-color-scheme: dark){
  [data-theme="system"]{
    --bg:#16150F; --panel:#1F1E17; --ink:#F3F0E8; --ink2:#D3CDC0; --grey:#A8A093; --faint:#948C7E;
    --line:#34322B; --line2:#272520;
    --ai:#A6BEEC; --ai-bg:#1A2132; --ai-line:#3A4767;
    --human:#EDACA6; --human-bg:#2C1B1A; --human-line:#5E3A37;
    --ok:#8FD0B1; --ok-bg:#152720;
    --on-ink:#16150F;
    --on-ink-soft:rgba(22,21,15,.86); --on-ink-mute:rgba(22,21,15,.74);
    --on-ink-faint:rgba(22,21,15,.55); --on-ink-dim:rgba(22,21,15,.45);
    --on-ink-line:rgba(22,21,15,.16); --on-ink-link:rgba(22,21,15,.66);
    --shadow:0 1px 3px rgba(0,0,0,.55);
    --veil:rgba(22,21,15,.93);
    color-scheme:dark;
  }
}

/* ---- the help card ------------------------------------------------------------------
   contextual-help.js injects its own stylesheet at boot, after this file, and paints a
   fixed gold-on-cream card. In high contrast that is exactly the surface someone cannot
   read, so it is overridden here — the attribute selector outranks the kit's bare ids
   regardless of which stylesheet loaded last. */
[data-theme="contrast"] #cx-help-chip{background:#000;color:#FFF;box-shadow:none;
  border:2px solid #000;opacity:1}
[data-theme="contrast"] #cx-help-card{background:#FFF;color:#000;border:2px solid #000;
  box-shadow:none;backdrop-filter:none}
[data-theme="contrast"] #cx-help-card .cxh-head{background:#000;color:#FFF;border-bottom:2px solid #000}
[data-theme="contrast"] #cx-help-card .cxh-title,
[data-theme="contrast"] #cx-help-card .cxh-toggle,
[data-theme="contrast"] #cx-help-card .cxh-max,
[data-theme="contrast"] #cx-help-card .cxh-close{color:#FFF}
[data-theme="contrast"] #cx-help-card .cxh-context,
[data-theme="contrast"] #cx-help-card .cxh-msgs,
[data-theme="contrast"] #cx-help-card .cxh-quickrow,
[data-theme="contrast"] #cx-help-card .cxh-inputrow,
[data-theme="contrast"] #cx-help-card .cxh-foot{background:#FFF;color:#000}
[data-theme="contrast"] #cx-help-card .cxh-msg.bot,
[data-theme="contrast"] #cx-help-card .cxh-quick,
[data-theme="contrast"] #cx-help-card .cxh-input{background:#FFF;color:#000;border:2px solid #000}
[data-theme="contrast"] #cx-help-card .cxh-msg.user,
[data-theme="contrast"] #cx-help-card .cxh-send{background:#000;color:#FFF;border:2px solid #000}

/* The appearance picker sits under the language one and is built from the same parts. */
.themepick{margin-top:14px}
.langbar.themebar{right:auto;left:16px}
@media (max-width:640px){.langbar.themebar{left:8px;right:8px;bottom:56px}}

/* ---------------------------------------------------------------- the profile dialog
 * The profile is what every other surface is specialised to, so it opens over whatever is
 * being read rather than replacing it. The panel is the same card language as the pages
 * inside it; only the backdrop and the frame are new.
 */
#profile-dialog{border:0;padding:0;background:transparent;max-width:min(640px,94vw);width:100%;
  max-height:88vh;color:var(--ink)}
#profile-dialog::backdrop{background:rgb(0 0 0 / .42)}
#profile-dialog .dlg{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  overflow:hidden;display:flex;flex-direction:column;max-height:88vh}
#profile-dialog header{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 18px;border-bottom:1px solid var(--line);font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint)}
#profile-dialog header b{font-weight:600;color:var(--ink)}
#profile-dialog header button{background:none;border:0;color:var(--grey);font-size:20px;
  line-height:1;cursor:pointer;padding:0 4px}
#profile-dialog header button:hover{color:var(--ink)}
#profile-dialog #profile-dialog-body{overflow-y:auto;padding:18px}
#profile-dialog .card{border:0;padding:0;margin:0;background:transparent}

/* The compact form, for the dialog.
 *
 * A confirmation people have to scroll to is one they learn to dismiss, so the modal variant
 * drops the hints (the server omits them) and tightens everything else until the whole form
 * and its buttons fit without scrolling on a laptop. The full page keeps the roomy version,
 * where somebody is filling this in for the first time and the notes earn their space.
 */
.card.compact .field{margin-bottom:9px}
/* Same exclusion as the roomy rules above, and for the same reason: the tightened padding is
 * about a text box, and applying it to a checkbox inflates the control instead of the field. */
.card.compact .field label:not(.opt){margin-bottom:3px}
.card.compact .field input:not([type=checkbox]):not([type=radio]),
.card.compact .field select{padding:7px 10px;font-size:13px}
.card.compact h3{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);
  margin:0 0 8px}
.card.compact h3 + .field{margin-top:0}
.card.compact .opt{padding:5px 9px;margin-bottom:4px}
.card.compact .opt .lb{font-size:12.5px}
/* The levels are a checkbox list and the tallest thing in the form; two columns halve it.
 *
 * A grid rather than two half-width inline-flex boxes. `width:calc(50% - 4px)` plus a 4px
 * margin comes to exactly 100%, so a single space of whitespace between two of the labels —
 * one `join('')` becoming `join('\n')` in the route that renders them — drops the second
 * column with nothing here to say why. Letting the container do the arithmetic cannot be
 * broken from the markup side, and the row is the unit anyway: the boxes stretch to a shared
 * height so their borders line up. The group's own label spans both columns.
 */
.card.compact .field:has(> .opt){display:grid;grid-template-columns:1fr 1fr;gap:4px}
.card.compact .field:has(> .opt) > label:not(.opt){grid-column:1 / -1}
.card.compact .field > .opt{margin-bottom:0}
.card.compact .row-actions{margin-top:14px}
/* The three tasks, on the dashboard.
 *
 * Numbered, because they run in an order and the order is the teaching. A shut phase is
 * dimmed and says why rather than disappearing — the same rule the rail follows. No bar, no
 * percentage, no "2 of 3 complete": phase two has no completion test and inventing one would
 * be the metric §11c.10 refuses.
 */
.phases{list-style:none;margin:0;padding:0;counter-reset:none}
.phase{display:flex;gap:14px;align-items:flex-start;padding:14px 0;border-bottom:1px solid var(--line)}
.phase:last-child{border-bottom:0;padding-bottom:0}
.phase:first-child{padding-top:0}
.phase .pn{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  font-size:12px;font-weight:600;background:var(--line2);color:var(--faint)}
.phase.open .pn{background:var(--ai-bg);color:var(--ai)}
.phase.cleared .pn{background:var(--ok-bg);color:var(--ok)}
.phase .pb{flex:1;min-width:0}
.phase h4{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:14px;margin:0 0 5px}
.phase p{font-size:13px;line-height:1.6;color:var(--ink2);margin:0 0 9px}
.phase.shut .pb h4,.phase.shut .pb p{color:var(--faint)}
/* Rendered by the server so it works with scripting off; the modal script hides it only once
 * the dialog is actually up, so a dialog that fails to open does not take the fallback away. */
.confirmprofile{margin-bottom:16px}

/* The header avatar is now the only route to the profile from the chrome — it left the rail,
   because the profile is the person and the rail is the phases of a project. So it has to
   carry a keyboard affordance of its own; hover alone serves the half of the audience holding
   a mouse. */
/* `.who` is now the <summary> of the account menu; hover and focus come from `.pick>summary`. */

/* ------------------------------------------------------- locked rail entries, and why
 * An educator reads this the way they read every LMS: shut, with a reason, and no doubt
 * about whether the thing exists. Never hidden — a section nobody can see is a section
 * nobody can ask about.
 */
.nav button.lockednav{display:block;width:100%;text-align:left;background:none;border:0;
  padding:7px 10px;font:inherit;font-size:13px;color:var(--faint);cursor:not-allowed}
.nav button.lockednav span[aria-hidden]{font-size:11px;margin-inline-end:2px;opacity:.8}
.nav .navwhy{font-size:11px;line-height:1.5;color:var(--faint);margin:2px 10px 8px;
  padding-inline-start:10px;border-inline-start:2px solid var(--line2)}
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Say when something is happening. A form that goes quiet for two seconds while a model is
 * called is indistinguishable from a form that did nothing. */
button[data-working]{opacity:.72;cursor:progress}
.workingnote{font-size:12px;color:var(--ai);margin-top:8px}

/* -------------------------------------------------------------- waiting for a navigation
 * The same commitment as above, extended to every link in the product — see `progress.js`
 * for why it arrives in stages rather than all at once.
 *
 * Stage 0 is running-but-silent: the click has been acknowledged on the control itself and
 * the wait is still short enough that nothing else should appear. So the container is in the
 * document from stage 0 and each piece is revealed by the stage it belongs to. */
[data-pending]{cursor:progress}
[data-pending] button,a[data-pending]{opacity:.72;transition:opacity .12s}

#working[hidden]{display:none}
/* Above the open dropdowns (60) and the floating switchers (50), so a click made through a
 * menu is not reported behind the menu it was made from; below the skip link (99), which
 * belongs to somebody navigating by keyboard and outranks a notice about waiting. */
#working{position:fixed;inset:0;z-index:70;pointer-events:none}

/* A bar with no percentage in it, and there will never be one: we cannot know how long a
 * round trip on somebody's connection will take, and a bar that fills to 80% and waits is a
 * claim we cannot support. It says something is happening. That is all we actually know. */
#working .wbar{position:absolute;top:0;left:0;right:0;height:3px;background:var(--line2);
  overflow:hidden;opacity:0;transition:opacity .15s ease-out}
#working[data-stage="1"] .wbar,#working[data-stage="2"] .wbar,#working[data-stage="3"] .wbar{opacity:1}
#working .wbar::after{content:'';position:absolute;top:0;bottom:0;left:0;width:40%;
  background:var(--ai);animation:wslide 1.15s ease-in-out infinite}
@keyframes wslide{0%{left:-40%}100%{left:100%}}

/* The waiting screen proper. A veil rather than a blackout: the page underneath stays
 * readable, because covering what somebody was reading in order to tell them to wait for it
 * is a poor trade. It does take pointer events at this stage — a second click after a second
 * of silence is the reasonable next move, and on a POST it posts twice. */
#working[data-stage="2"],#working[data-stage="3"]{pointer-events:auto;background:var(--veil)}
#working .wcard{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  display:none;flex-direction:column;gap:6px;align-items:center;text-align:center;
  max-width:min(420px,88vw);padding:20px 24px;background:var(--panel);
  border:var(--border) solid var(--line);border-radius:10px;box-shadow:var(--shadow)}
#working[data-stage="2"] .wcard,#working[data-stage="3"] .wcard{display:flex}
#working .wtitle{font-weight:600;color:var(--ink)}
#working .wnote{font-size:13px;color:var(--grey);line-height:1.55}
#working .wretry{margin-top:8px}

/* The global reduced-motion rule collapses every animation to nothing, which would leave the
 * bar above as a stationary 40% stub — a determinate bar stuck at 40%, which is exactly the
 * lie the indeterminate one exists to avoid. So it becomes a full-width tint instead: no
 * movement, and no implied fraction either. */
@media (prefers-reduced-motion: reduce){
  #working .wbar::after{width:100%;left:0;opacity:.55}
}

/* -------------------------------------------------------- options for a field, on request
 * Visually subordinate to the field itself, and never inside it. What the educator types is
 * the answer; this is a list they may take one from, and the layout should not let anyone
 * mistake the second for the first.
 */
.sugg-ask{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:8px 0 0}
.sugg-hint{font-size:11.5px;color:var(--faint);line-height:1.5;flex:1;min-width:220px}
.sugg-panel:empty{display:none}
.sugg-panel{margin-top:10px}
.sugg-out{border:1px solid var(--ai-line);background:var(--ai-bg);border-radius:8px;padding:12px 14px}
.sugg-head{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ai);margin:0 0 8px}
.sugg-basis{font-size:11.5px;color:var(--ink2);margin:0 0 10px;line-height:1.55}
.sugg-list{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px}
/* The option and, under it, where in the document it was found. Stacked inside the item
   rather than run on after the chip, so the row of chips still wraps as a row of chips and
   the locator stays attached to the one it belongs to. */
.sugg-list li{margin:0;display:flex;flex-direction:column;gap:3px;align-items:flex-start}
.sugg-list button{text-align:left}
.sugg-where{font-size:11px;color:var(--ai);letter-spacing:.02em;padding-inline-start:2px}

/* Help for the field that may never be suggested into.
 *
 * Deliberately not `.sugg-out`: that panel is blue, which is the AI colour, and this is the
 * one field where the point is that no model has been anywhere near it. It reads as the
 * page's own prose — a disclosure the educator opens — and it holds no control, so there is
 * nothing here to take even by accident. */
/* What the question does and does not reach, under the question itself. Part of the label
   rather than a hint below the box, because it changes what is being asked — somebody who
   reads it after staring at an empty textarea has already decided the question was about
   their syllabus. Normal weight, so it reads as the second half of the question and not as
   an instruction. */
.field label .qscope{display:block;margin-top:3px;font-weight:400;font-size:12px;
  line-height:1.55;color:var(--grey)}

/* The sort: how it works, above the thing it explains. */
.sorthow{font-size:13px;line-height:1.6;color:var(--ink2);margin:0 0 4px}
.sortcount{font-size:12px;color:var(--faint);margin:10px 0}

/* The column's own control. It is what makes the exercise reachable without a mouse, so it
   is a real button rather than a hint that the column is clickable — and it is quiet until
   there is something to place, because a row of five live buttons offering to place nothing
   is five ways to be told no. */
.bucketdrop{display:block;width:100%;margin-top:10px;padding:6px 8px;font-size:11.5px;
  border:1px dashed var(--line);background:none;color:var(--grey);border-radius:var(--radius);
  cursor:pointer}
.bucketdrop:hover:not(:disabled){border-style:solid;border-color:var(--human);color:var(--human)}
.bucketdrop:disabled{opacity:.45;cursor:default}

/* The "?" beside a label, and the meaning it gives on request.
 *
 * A disclosure rather than a tooltip: a definition that appears because a cursor passed over
 * it has been read whether or not it was wanted, and this layer's whole question is what
 * somebody already knew. The panel is absolutely positioned so opening one does not reflow
 * the pool and move the label somebody was about to click.
 *
 * It is drawn as the second segment of one control rather than as a chip of its own. Twenty
 * labels wrap across several rows, and a "?" that floats free of its label is a question
 * about whichever label the eye lands on — so: shared surface, one divider, square inner
 * corners. The pair is one object offering two things. */
.poolitem{display:inline-flex;align-items:stretch;gap:0;position:relative}
.poolitem > button[data-label]{border-top-right-radius:0;border-bottom-right-radius:0}
.whatis{position:relative;display:flex}

/* At rest it takes the label's own surface. A grey fill welded to a white button reads as
   the greyed-out half of a control, which is the one thing this must not look like — what
   marks it operable is the divider and the weight of the glyph, and what confirms it is the
   tint that arrives on hover, focus and open.
 *
 * `--ink2` rather than `--grey`: at this size the muted grey is under 4.5:1 on --panel in
 * three of the five themes, and the whole glyph is one character with nothing around it to
 * read it from. `min-width` carries it past the 24px target floor (WCAG 2.2 SC 2.5.8) —
 * padding alone left it at 23px in English, while zh-Hans/zh-Hant send a fullwidth ？ that
 * sets its own width, so the box is centred on the glyph rather than sized to it.
 *
 * `pointer`, not `help`. `help` is the cursor for something that explains itself when the
 * cursor arrives, which is exactly what this refuses to be; and with the assistant loaded
 * the click never opens the disclosure at all — `app.js` takes it and opens the help card. */
.whatis > summary{list-style:none;display:flex;align-items:center;justify-content:center;
  min-width:26px;height:100%;padding:0 7px;
  border:var(--border) solid var(--line);border-inline-start:0;
  border-radius:0 var(--radius) var(--radius) 0;
  background:var(--panel);color:var(--ink2);font-size:13px;font-weight:700;line-height:1;
  cursor:pointer;transition:background .12s,color .12s,border-color .12s}
.whatis > summary::-webkit-details-marker{display:none}
.whatis > summary::marker{content:""}
.whatis > summary:hover{background:var(--human-bg);color:var(--human);border-color:var(--human-line)}
.whatis[open] > summary{background:var(--human-bg);color:var(--human);border-color:var(--human-line)}

/* `summary` is absent from the global focus rule, which lists a·button·input·textarea·select
   — so the one control here that is reachable *only* as a disclosure was the one with no
   ring of ours. `z-index` lifts it clear of the label button it is welded to, whose border
   would otherwise be painted over the near edge of the outline. */
.whatis > summary:focus-visible{outline:var(--focus) solid var(--ai);outline-offset:2px;
  z-index:2}

/* Selected, the label goes to --ink and the "?" goes with it: a dark chip with a pale tab
   still attached reads as a control half of which has stopped working, and the tab is the
   same control. The divider is an inset shadow rather than a border so that selecting a
   label does not move it a pixel. `:has` because the state lives on the previous sibling;
   where it is unsupported the pair simply stays as it was before. */
.poolitem:has(> button[aria-pressed="true"]) > .whatis > summary{
  background:var(--ink);color:var(--on-ink);border-color:var(--ink);
  box-shadow:inset 1px 0 0 var(--on-ink-line)}
.poolitem:has(> button[aria-pressed="true"]) > .whatis > summary:hover,
.poolitem:has(> button[aria-pressed="true"]) > .whatis[open] > summary{
  background:var(--human);color:var(--on-ink);border-color:var(--human)}

.whatisbody{position:absolute;z-index:30;top:calc(100% + 6px);left:0;width:max-content;
  max-width:min(320px,80vw);padding:11px 13px;background:var(--panel);
  border:var(--border) solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);
  text-align:left;white-space:normal}
.whatisbody p{margin:0;font-size:12.5px;line-height:1.6;color:var(--ink2)}
.whatisbody p.askmore{margin-top:8px;padding-top:8px;border-top:1px solid var(--line2);
  font-size:11.5px;color:var(--faint)}
/* Near the right edge the panel would otherwise run off the page. */
.pool > .poolitem:nth-last-child(-n+3) .whatisbody{left:auto;right:0}

/* One label, one meaning, opened on request — the help that could not be offered before the
   answer was given. */
.glossary{display:flex;flex-direction:column;gap:2px}
.glossary details{border-bottom:1px solid var(--line2)}
.glossary summary{padding:8px 2px;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer}
.glossary summary:hover{color:var(--human)}
.glossary p{margin:0 2px 10px;font-size:12.5px;line-height:1.65;color:var(--ink2)}

.ownhelp{margin:8px 0 0}
.ownhelp > details{margin-top:8px;border-inline-start:2px solid var(--line);padding-inline-start:12px}
.ownhelp summary{font-size:12px;font-weight:600;color:var(--ink2);cursor:pointer;
  padding:2px 0;list-style-position:outside}
.ownhelp summary:hover{color:var(--ink)}
.ownhelp .note{margin:6px 0 8px;font-size:11.5px}
.ownhelp ul{margin:0;padding-inline-start:18px;display:flex;flex-direction:column;gap:7px}
.ownhelp li{font-size:12.5px;line-height:1.6;color:var(--ink2)}
/* The examples are somebody else's words, so they are set as quotations and attributed —
   the same treatment `.quote` gives every other verbatim thing in the product. */
/* A frame and the control that puts it in the box. The frame is set in the serif the product
   uses for anybody's words, because that is what it is about to become — the blanks are set
   apart so it reads as a shape with holes rather than as a sentence somebody wrote. */
.ownhelp .ownfill li{list-style:none;margin-inline-start:-18px;display:flex;flex-wrap:wrap;
  align-items:baseline;gap:8px}
.ownhelp .ownfill p{margin:0;flex:1;min-width:min(280px,100%);font-family:var(--serif);
  font-size:13px;line-height:1.65;color:var(--ink2)}
.ownhelp .ownfill button{flex:none}

.ownhelp .ownex li{list-style:none;margin-inline-start:-18px}
.ownhelp .ownex p{margin:0;font-family:var(--serif);font-size:13px;line-height:1.65;color:var(--ink)}
.ownhelp .ownex cite{display:block;margin-top:3px;font-style:normal;font-size:11px;color:var(--faint)}
.sugg-foot{font-size:11.5px;color:var(--faint);margin:10px 0 0;line-height:1.55}

/* ------------------------------------------------- the nested selection at Layer 0
 * The inherited-tier questions belong to the span above, so they read as a bracket around
 * the design rather than as more of it. Shown for every span and revealed by the choice, so
 * the whole shape of the funnel is legible before anything is picked — and so the form still
 * works with scripting off, where all of them stay visible and unwanted ones are discarded
 * on the server.
 */
.inherits{margin:0}
.inherits .inherit{border-inline-start:2px solid var(--line2);padding-inline-start:12px}

/* The composition: one design across the tiers, not four competing picks. */
.composition{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.composition .plus{color:var(--faint);font-size:13px;padding:0 2px}

/* ------------------------------------------------------- help, on the step it belongs to
 * Written, not generated: an explanation that only exists when a model is reachable is not
 * help. Sits above the form because it is the reason for the questions, not a footnote to
 * them, and is marked `data-help` so the floating assistant has something specific to
 * answer about.
 */
.stephelp{border:1px solid var(--line);border-inline-start:3px solid var(--ai);border-radius:8px;
  background:var(--panel);padding:14px 16px;margin-bottom:16px}
.stephelp h4{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ai);margin:0 0 8px}
.stephelp p{font-size:13px;line-height:1.65;color:var(--ink2);margin:0 0 8px}
.stephelp p:last-child{margin-bottom:0}
.stephelp .not{color:var(--grey);font-size:12.5px}
.stephelp .not b{color:var(--ink2);font-weight:600}
.wizardbar .state.shut .sn{color:var(--faint)}

/* The answers already given, on the page of the step that depends on them.
 *
 * Open by default — the point is to be readable without a click — but collapsible, because on
 * the last steps it carries a dozen rows and somebody re-reading their own material should be
 * able to fold it away. `.m` is deliberately allowed to wrap here: these values are a term's
 * worth of an educator's own sentences, and the ledger's nowrap would truncate them.
 */
.sofar{border:1px solid var(--line);border-radius:8px;background:var(--panel);
  padding:12px 16px;margin-bottom:16px}
.sofar > summary{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink2);cursor:pointer;list-style:none}
.sofar > summary::-webkit-details-marker{display:none}
.sofar > summary::before{content:"▾ ";color:var(--faint)}
.sofar:not([open]) > summary::before{content:"▸ "}
.sfgroup{margin-top:12px}
.sfgroup h4{display:flex;justify-content:space-between;align-items:baseline;gap:12px;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin:0 0 4px}
.sfgroup h4 a{font-size:11px;font-weight:500;letter-spacing:0;text-transform:none;
  color:var(--ai);text-decoration:none;flex:none}
.sfgroup h4 a:hover{text-decoration:underline}
.sfgroup .li{padding:5px 0}
.sfgroup .li .m{white-space:normal;max-width:60%;color:var(--ink2)}

/* Asking about a design that is already on record.
 *
 * The educator's turn and the reply are visibly different objects, and the reply carries the
 * AI rule down its left edge that every other model-produced surface in this app carries —
 * somebody scrolling past should not have to read a paragraph to find out whose words those
 * are. What is deliberately not styled like a chat is the box itself: a textarea and a button
 * that says Ask, rather than a message bar with a send arrow, because an inquiry here is a
 * question about a document and not a conversation with a companion.
 */
.askthread{margin-bottom:16px}
.askturn{border-radius:8px;padding:12px 14px;margin-bottom:10px}
.askturn h5{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--faint);margin:0 0 6px}
.askturn p{font-size:13.5px;line-height:1.7;color:var(--ink);margin:0}
.askturn.user{background:var(--line2);border:1px solid var(--line)}
.askturn.assistant{background:var(--ai-bg);border:1px solid var(--ai-line);border-inline-start:3px solid var(--ai)}
.askturn.assistant h5{color:var(--ai)}
/* Pending and failed say so in the text; the fade and the rule are only a second signal, so
 * neither state depends on colour alone. */
.askturn.pending p{color:var(--grey);font-style:italic}
.askturn.failed{border-inline-start-color:var(--human);background:var(--human-bg);border-color:var(--human-line)}
.askturn.failed h5{color:var(--human)}
.askturn .handback{margin-top:10px;padding-top:10px;border-top:1px solid var(--ai-line)}
.askturn .handback p{font-size:12.5px;color:var(--ink2)}
.askturn .askbasis{margin-top:10px}
.askturn .askbasis ul{margin:0;padding-inline-start:18px}
.askturn .askbasis li{font-size:12.5px;line-height:1.6;color:var(--ink2)}
.askturn .note{margin-top:10px}
.askturn .askq{margin-top:12px;font-size:13.5px;line-height:1.7;color:var(--ink2);font-style:italic}
.askform{margin-top:12px}
.askform textarea{width:100%;min-height:72px}
/* Openers, not suggestions: they fill the question box and nothing else. Rendered as plain
 * buttons in a wrap so a long one is readable rather than truncated into a chip. */
.askopeners{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 12px}
.askopeners button{text-align:left}

/* Asking about one line of the critique.
   A `<details>` inside the block it is about, so a page with six readings on it is six
   sentences and six closed disclosures rather than six open forms. It inherits the ask
   styling above — the thread, the openers and the basis are the same elements the design
   record uses, driven by the same script. */
.askhere{margin-top:12px;border-top:1px solid var(--line2);padding-top:10px}
.askhere>summary{font-size:12.5px;color:var(--grey);cursor:pointer;list-style:none}
.askhere>summary::-webkit-details-marker{display:none}
.askhere>summary::before{content:"?";display:inline-grid;place-items:center;width:16px;height:16px;
  margin-inline-end:7px;border:1px solid var(--line);border-radius:50%;font-size:10.5px;vertical-align:-2px}
.askhere>summary:hover{color:var(--ink2)}
.askhere[open]>summary{color:var(--ink2);margin-bottom:8px}
.askhere .askform{margin-top:8px}
.askhere .askform textarea{min-height:56px}

