/* ═══════════════════════════════════════════════════════════════
   English Academy — components

   Every value here comes from a token in tokens.css, which theme.php
   overrides from the Design screen. There is no colour, font name or
   fixed size below that an administrator cannot change without code.

     1  base and rhythm      6  sections and lists
     2  type scale           7  the skills grid
     3  layout               8  feedback
     4  surfaces             9  activities
     5  controls            10  landing, admin, responsive
   ═══════════════════════════════════════════════════════════════ */

/* ── 1. base and rhythm ─────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background-color:var(--paper);
  color:var(--ink);
  font-family:var(--ui);
  font-size:16px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
/* THE BACKGROUND PICTURE, AND WHY IT HANGS OFF A CLASS.
   theme.php is one cached stylesheet served to every page, so the image
   cannot be switched there per page — whatever it says is true
   everywhere at once. The picture therefore lives on .has-bg, which
   index.php puts on the body only for the pages chosen on the Design
   screen. A page that is not chosen gets the plain paper colour, and the
   scrim with it: without this the scrim still painted a flat wash over
   pages that had no picture under it, which is the faint grey haze on
   the working pages. */
body.has-bg{
  background-image:var(--bg-image);
  background-size:var(--bg-size);
  background-position:var(--bg-pos);
  background-repeat:var(--bg-repeat);
  background-attachment:fixed;
}
/* the scrim sits between a background image and the content */
body.has-bg::before{
  content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:var(--paper);opacity:var(--bg-scrim);
}
.top,.wrap{position:relative;z-index:1}
button,input,textarea,select{font:inherit;color:inherit;margin:0}
img{max-width:100%;height:auto;display:block}
a{color:var(--trace);text-underline-offset:2px}
:focus-visible{outline:2px solid var(--trace);outline-offset:3px;border-radius:2px}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ── 2. type scale ──────────────────────────────────────── */
h1,h2,h3{margin:0;font-family:var(--ui);letter-spacing:-.02em;line-height:1.2}
h1{font-size:clamp(26px,3.4vw,34px);font-weight:700;margin-bottom:var(--s2)}
h2{font-size:20px;font-weight:700;letter-spacing:-.015em;margin-bottom:var(--s3)}
h3{font-size:15px;font-weight:600;letter-spacing:-.005em;margin-bottom:var(--s2)}
p{margin:0 0 var(--s3)}
p:last-child{margin-bottom:0}

.lede{font-size:17px;line-height:1.6;color:var(--slate);max-width:60ch;margin-bottom:var(--s6)}
.small{font-size:14px;line-height:1.55;color:var(--slate)}
.mono{font-family:var(--data);font-size:13px}

/* the one small-caps label, used only above a title */
.eyebrow{
  display:block;font-family:var(--data);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);margin-bottom:var(--s2);
}
.eyebrow a{color:var(--muted);text-decoration:none}
.eyebrow a:hover{color:var(--ink)}

/* learner-facing prose in the reading face, platform voice in the ui face */
.learner,.passage,.fb__goal,.fb__reply,.fix__body,.verdict,.q__stem,
.land__card p,.pickbig__d,.good{font-family:var(--text)}

/* ── 3. layout ──────────────────────────────────────────── */
.wrap{max-width:var(--maxw);margin:0 auto;padding:var(--s6) var(--s4) calc(var(--s8) * 1.4)}
.narrow{max-width:min(560px,100%);margin:0 auto}

.top{position:sticky;top:0;z-index:20;background:var(--paper);border-bottom:1px solid var(--line)}
.top__in{
  max-width:var(--maxw);margin:0 auto;padding:var(--s3) var(--s4);
  display:flex;align-items:center;justify-content:space-between;gap:var(--s4);flex-wrap:wrap;
}
.brand{
  display:inline-flex;align-items:center;gap:var(--s2);
  font-weight:700;font-size:17px;letter-spacing:-.02em;text-decoration:none;color:var(--ink);
}
.brand__logo{height:24px;width:auto}
.tabs{display:flex;gap:2px;flex-wrap:wrap}
.tab{
  padding:var(--s2) var(--s3);border-radius:var(--r);border:0;background:none;
  color:var(--slate);font-size:14.5px;text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:background .12s,color .12s;
}
.tab:hover{background:var(--line-soft);color:var(--ink)}
.tab.on{background:var(--ink);color:var(--paper)}

.crumb{font-size:13.5px;color:var(--muted);margin-bottom:var(--s3)}
.crumb a{color:var(--muted);text-decoration:none}
.crumb a:hover{color:var(--ink);text-decoration:underline}

/* ── 4. surfaces ────────────────────────────────────────── */
/* one card. everything that used to be its own component is now a
   variant of this, which is why the pages finally share a rhythm. */
.card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s5);margin-bottom:var(--s4);
}
.card:last-child{margin-bottom:0}
.card > h2:first-child,.card > h3:first-child,.card > .eyebrow:first-child{margin-top:0}

.tile{
  display:block;background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4) var(--s5);margin-bottom:var(--s2);text-decoration:none;color:inherit;
  transition:border-color .14s,transform .14s,box-shadow .14s;
}
a.tile:hover{border-color:var(--ink);transform:translateY(-1px);box-shadow:0 3px 12px rgba(0,0,0,.05)}
.tile--flat{background:none;border-style:dashed}
.tile__meta{font-size:12.5px;color:var(--muted);margin-bottom:var(--s1)}
.tile__t{font-weight:600;font-size:17px;letter-spacing:-.015em;margin-bottom:2px}
.tile__d{font-size:14.5px;color:var(--slate);line-height:1.5}

.grid-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:var(--s3)}
.pick{
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4);min-height:134px;text-decoration:none;color:inherit;
  transition:border-color .14s,transform .14s,box-shadow .14s;
}
a.pick:hover{border-color:var(--ink);transform:translateY(-2px);box-shadow:0 4px 14px rgba(0,0,0,.06)}
.pick__t{font-weight:600;font-size:16.5px;letter-spacing:-.015em;margin-bottom:var(--s1)}
.pick__d{font-size:14px;color:var(--slate);line-height:1.45;margin-bottom:var(--s3)}
.pick__n{margin-top:auto;font-family:var(--data);font-size:11.5px;color:var(--muted)}
.pick--soon{opacity:.5}
.pick--soon .pick__n{color:var(--mark)}

.pickbig{
  display:block;width:100%;text-align:left;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s5);margin-bottom:var(--s3);text-decoration:none;color:inherit;cursor:pointer;
  transition:border-color .14s,transform .14s,box-shadow .14s;
}
.pickbig:hover{border-color:var(--ink);transform:translateY(-2px);box-shadow:0 4px 14px rgba(0,0,0,.06)}
.pickbig__t{display:block;font-family:var(--ui);font-weight:700;font-size:18px;
  letter-spacing:-.015em;margin-bottom:var(--s2)}
.pickbig__d{display:block;font-size:15.5px;line-height:1.55;color:var(--slate)}

.start-here{border-color:var(--trace);background:var(--trace-bg)}
.notice{
  background:var(--mark-bg);border-left:3px solid var(--mark);
  border-radius:0 var(--r) var(--r) 0;padding:var(--s3) var(--s4);
  margin-bottom:var(--s4);font-size:15px;
}
.empty{
  border:1px dashed var(--line);border-radius:var(--r);
  padding:var(--s6) var(--s5);text-align:center;color:var(--slate);margin-bottom:var(--s4);
}

/* ── 5. controls ────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  background:var(--ink);color:var(--paper);border:1px solid var(--ink);border-radius:var(--r);
  padding:11px var(--s5);
  font-family:var(--ui);font-weight:600;font-size:15px;letter-spacing:-.01em;
  text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:background .12s,border-color .12s,transform .12s;
}
.btn:hover{background:var(--slate);border-color:var(--slate)}
.btn:active{transform:translateY(1px)}
.btn:disabled{opacity:.4;cursor:default;transform:none}
.btn--ghost{background:none;color:var(--ink);border-color:var(--line)}
.btn--ghost:hover{background:var(--line-soft);color:var(--ink);border-color:var(--slate)}
.btn--sm{padding:8px var(--s3);font-size:13.5px}
.btn--lg{padding:14px var(--s6);font-size:16.5px}
.row{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center;margin-top:var(--s5)}

input[type=text],input[type=password],input[type=url],input[type=number],textarea,select{
  width:100%;background:var(--card);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r);padding:11px var(--s3);
  font-family:var(--text);font-size:16px;line-height:1.5;
  transition:border-color .12s,box-shadow .12s;
}
select{font-family:var(--ui)}
textarea{font-size:17px;line-height:1.7;resize:vertical;min-height:120px}
input:focus,textarea:focus,select:focus{
  border-color:var(--slate);box-shadow:0 0 0 3px var(--trace-bg);outline:none;
}
input::placeholder,textarea::placeholder{color:var(--muted)}

.ask{text-align:center;padding:var(--s6) 0 var(--s5)}
.ask__h{margin-bottom:var(--s5)}
.ask__note{font-size:13.5px;color:var(--muted);max-width:46ch;margin:var(--s5) auto 0;line-height:1.55}
.pills{display:flex;flex-wrap:wrap;gap:var(--s3);justify-content:center;margin-bottom:var(--s3)}
.pill{
  display:inline-block;background:var(--ink);color:var(--paper);
  border:2px solid var(--ink);border-radius:999px;padding:13px 30px;
  font-family:var(--ui);font-weight:700;font-size:17px;letter-spacing:-.01em;text-decoration:none;
  transition:transform .14s,box-shadow .14s,background .14s,border-color .14s;
}
a.pill:hover{transform:translateY(-2px);box-shadow:0 5px 16px rgba(0,0,0,.16);
  background:var(--slate);border-color:var(--slate)}
.pill--off{background:none;color:var(--muted);border-color:var(--line);cursor:default}
.pill--static{cursor:default}

.tag{
  display:inline-block;font-family:var(--data);font-size:10.5px;letter-spacing:.08em;
  text-transform:uppercase;padding:3px 7px;border-radius:3px;
  background:var(--line-soft);color:var(--slate);vertical-align:1px;
}
.tag--mark{background:var(--mark-bg);color:var(--mark)}
.tag--trace{background:var(--trace-bg);color:var(--trace)}

.spin{
  display:inline-block;width:12px;height:12px;vertical-align:-1px;
  border:2px solid var(--line);border-top-color:var(--slate);border-radius:50%;
  animation:sp .7s linear infinite;
}
@keyframes sp{to{transform:rotate(360deg)}}

/* ── 6. sections and lists ──────────────────────────────── */
.sec{margin-bottom:var(--s6)}
.sec:last-child{margin-bottom:0}
.sec__h{
  font-size:15px;font-weight:600;letter-spacing:-.01em;color:var(--ink);
  padding-bottom:var(--s2);margin-bottom:var(--s3);border-bottom:1px solid var(--line);
}
.sec--quiet{opacity:.6}

table{width:100%;border-collapse:collapse;font-size:15px}
th{
  text-align:left;font-family:var(--data);font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);font-weight:400;
  padding:0 var(--s3) var(--s2) 0;border-bottom:1px solid var(--line);
}
td{padding:var(--s3) var(--s3) var(--s3) 0;border-bottom:1px solid var(--line-soft);vertical-align:top}
tr:last-child td{border-bottom:0}

.goal{
  display:flex;gap:var(--s3);align-items:flex-start;
  padding:var(--s3) var(--s4);border:1px solid var(--line);border-radius:var(--r);
  margin-bottom:var(--s2);cursor:pointer;background:var(--card);transition:border-color .12s;
}
.goal:hover{border-color:var(--slate)}
.goal.is-on{border-color:var(--ink);box-shadow:inset 3px 0 0 var(--mark)}
.goal input{margin-top:4px;flex:none;accent-color:var(--mark)}

/* ── 7. the skills grid ─────────────────────────────────── */
.grid{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;margin-bottom:var(--s4);
}
.grid__head,.grow{
  /* The number of level columns comes from LEVELS in lib/profile.php,
     passed in as --levels on .grid. It was hardcoded to 4, so widening
     the ladder to A1-C2 pushed the last two levels onto a second row. */
  display:grid;grid-template-columns:1fr repeat(var(--levels,6),52px);
  gap:var(--s2);align-items:center;padding:var(--s2) var(--s5);
}
.grid__head{padding-top:var(--s4);padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
.grid__lvl{font-family:var(--data);font-size:11.5px;color:var(--muted);text-align:center;letter-spacing:.06em}
.grid__area{
  font-size:13px;font-weight:600;color:var(--slate);
  padding:var(--s5) var(--s5) var(--s2);border-top:1px solid var(--line-soft);
}
.grid__area:first-of-type{border-top:0;padding-top:var(--s4)}
.grow{transition:background .1s}
.grow:hover{background:var(--line-soft)}
.grow__name{display:flex;align-items:center;gap:var(--s3);min-width:0}
.grow__label{font-size:15.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dots{display:flex;gap:3px;flex:none}
.dot{width:7px;height:7px;border-radius:50%;background:var(--line);flex:none}
.dot.has{background:var(--trace)}

.cell{
  height:34px;border-radius:3px;background:var(--line-soft);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--data);font-size:12px;color:var(--muted);
}
.cell.strong{background:var(--gold-bg);box-shadow:inset 0 0 0 1.5px var(--gold);color:var(--gold)}
.cell.weak{background:var(--mark-bg);box-shadow:inset 0 0 0 1.5px var(--mark);color:var(--mark)}
.cell.estimated{background:var(--trace-bg);color:var(--trace)}
.key{
  display:flex;gap:var(--s5);flex-wrap:wrap;
  padding:var(--s4) var(--s5);border-top:1px solid var(--line);
  font-size:13px;color:var(--slate);
}
.key span{display:flex;align-items:center;gap:var(--s2)}
.sw{width:14px;height:14px;border-radius:3px;background:var(--line-soft);flex:none}

/* ── 8. feedback ────────────────────────────────────────── */
.fb__reply{
  background:var(--trace-bg);border-left:3px solid var(--trace);
  border-radius:0 var(--r) var(--r) 0;padding:var(--s4) var(--s5);
  margin-bottom:var(--s6);font-size:17px;line-height:1.6;
}
.fb__part{margin-bottom:var(--s6)}
.fb__h{
  font-size:15px;font-weight:600;color:var(--ink);
  padding-bottom:var(--s2);margin-bottom:var(--s3);border-bottom:1px solid var(--line);
}
.fb__goal{font-size:17px;line-height:1.6}

.good{
  border:1px solid var(--gold);background:var(--gold-bg);border-radius:var(--r);
  padding:var(--s4) var(--s5);margin-bottom:var(--s3);font-size:16px;line-height:1.6;
}
.good b{
  display:block;font-family:var(--ui);font-weight:600;font-size:15px;
  letter-spacing:-.01em;margin-bottom:var(--s1);
}

.fix{
  border:1px solid var(--line);background:var(--card);border-radius:var(--r);
  margin-bottom:var(--s2);overflow:hidden;transition:border-color .12s;
}
.fix:hover{border-color:var(--slate)}
.fix.open{border-color:var(--mark);box-shadow:0 0 0 1px var(--mark)}
.fix__t{
  width:100%;text-align:left;background:none;border:0;cursor:pointer;
  padding:var(--s4) var(--s5);display:flex;justify-content:space-between;
  align-items:center;gap:var(--s4);
}
.fix__t:hover{background:var(--line-soft)}
.fix__title{font-family:var(--ui);font-weight:600;font-size:16px;letter-spacing:-.01em}
.fix__n{font-family:var(--data);font-size:11.5px;color:var(--muted);flex:none;letter-spacing:.04em}
.fix.open .fix__n{color:var(--mark)}
.fix__body{padding:0 var(--s5) var(--s5);font-size:16px;line-height:1.65}
.fix__ev{
  background:var(--paper);border-left:2px solid var(--mark);
  border-radius:0 var(--r) var(--r) 0;padding:var(--s3) var(--s4);margin-bottom:var(--s3);
}
.fix__do{
  font-family:var(--ui);font-weight:600;font-size:15.5px;
  margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line-soft);
}
.hint{background:var(--paper);border-radius:var(--r);padding:var(--s3) var(--s4);
  margin-top:var(--s3);font-size:15.5px;line-height:1.6}
.hint__n{font-family:var(--data);font-size:10.5px;color:var(--muted);
  letter-spacing:.1em;text-transform:uppercase;margin-bottom:var(--s1)}
.flagbtn{
  background:none;border:0;padding:0;margin-top:var(--s4);
  color:var(--muted);font-size:13px;cursor:pointer;text-decoration:underline;
}
.flagbtn:hover{color:var(--mark)}

/* counted measures carry numbers. judged ones never do. */
.counted{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:var(--s2)}
.counted div{background:var(--paper);border-radius:var(--r);padding:var(--s4) var(--s3);text-align:center}
.counted b{
  display:block;font-family:var(--data);font-size:23px;font-weight:500;
  letter-spacing:-.02em;margin-bottom:2px;
}
.counted span{display:block;font-size:12.5px;color:var(--slate);line-height:1.35}

/* ── 9. activities ──────────────────────────────────────── */
.q{border-top:1px solid var(--line-soft);padding:var(--s5) 0}
.q:first-of-type{border-top:0;padding-top:0}
.q__stem{font-size:17px;line-height:1.55;margin-bottom:var(--s3)}
.opt{
  display:block;width:100%;text-align:left;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);
  padding:12px var(--s4);margin-bottom:var(--s2);
  font-family:var(--text);font-size:16px;cursor:pointer;
  transition:border-color .12s,background .12s;
}
.opt:hover{border-color:var(--slate)}
.opt.right{border-color:var(--trace);background:var(--trace-bg)}
.opt.wrong{border-color:var(--mark);background:var(--mark-bg)}
.opt.chosen{border-color:var(--ink);background:var(--line-soft)}
.opt--radio{display:flex;gap:var(--s3);align-items:flex-start}
.opt--radio input{margin-top:4px;flex:none;accent-color:var(--mark)}

.verdict{border-radius:var(--r);padding:var(--s4) var(--s5);margin-top:var(--s3);
  font-size:16px;line-height:1.65}
.verdict--meaning{background:var(--trace-bg);border-left:3px solid var(--trace)}
.verdict--decode{background:var(--mark-bg);border-left:3px solid var(--mark)}
.verdict b{display:block;font-family:var(--ui);font-weight:600;font-size:15.5px;
  letter-spacing:-.01em;margin-bottom:var(--s1)}

.probe{background:var(--card);border:1px solid var(--mark);border-radius:var(--r);
  padding:var(--s5);margin-top:var(--s3)}
.probe__h{font-family:var(--data);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mark);margin-bottom:var(--s2)}

.passage{font-size:17.5px;line-height:1.85}

/* Hung on #passage, not .passage.
   TOEFL shows the same text three ways — plain, as an email, as a social
   post — and only the plain one carries the .passage class. All three
   carry id="passage", which is what the JavaScript already used. Scoped
   to the class, none of this reached the email or the post: no saveable
   words, and no highlight on the sentence a learner is asked to click. */
#passage w{cursor:pointer;border-bottom:1px dotted var(--line);transition:background .1s}
#passage w:hover{background:var(--gold-bg)}
#passage w.is-saved{background:var(--gold-bg);border-bottom:1px solid var(--gold)}
#passage .sent{display:inline;text-decoration:none}
#passage .sent.pickable{
  cursor:pointer;border-radius:3px;padding:2px 3px;margin:0 -1px;
  box-shadow:inset 0 -1px 0 var(--line);transition:background .12s,box-shadow .12s;
}
#passage .sent.pickable:hover{background:var(--trace-bg);box-shadow:inset 0 0 0 1.5px var(--trace)}
#passage .sent.pickable w{cursor:pointer;border-bottom:0}
#passage .sent.pickable w:hover{background:none}
.script{font-family:var(--text);font-size:17px;line-height:1.85;
  background:var(--paper);padding:var(--s5);border-radius:var(--r);margin-top:var(--s3)}
.heard{font-family:var(--data);font-size:13.5px;line-height:1.9;
  background:var(--paper);padding:var(--s3) var(--s4);border-radius:var(--r);margin-top:var(--s3)}
.heard s{color:var(--mark);text-decoration:none;background:var(--mark-bg);padding:1px 4px;border-radius:3px}
.heard em{font-style:normal;color:var(--trace)}

.player{background:var(--ink);color:var(--paper);border-radius:var(--r);padding:var(--s5)}
.player .btn{background:var(--paper);color:var(--ink);border-color:var(--paper)}
.player .btn:hover{background:#fff;border-color:#fff}
.player .btn--ghost{background:none;color:var(--paper);border-color:rgba(255,255,255,.28)}
.player .btn--ghost:hover{background:rgba(255,255,255,.12);color:var(--paper)}
.player__state{font-family:var(--data);font-size:12px;opacity:.7;margin-left:auto}
.wave{display:flex;gap:3px;align-items:flex-end;height:30px;margin-bottom:var(--s4)}
.wave i{flex:1;background:rgba(255,255,255,.22);border-radius:1px;height:30%}
.wave.playing i{animation:w .9s ease-in-out infinite}
.wave i:nth-child(3n){animation-delay:.15s}
.wave i:nth-child(3n+1){animation-delay:.3s}
@keyframes w{0%,100%{height:22%}50%{height:100%}}

.drafts{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s3)}
.draft{font-family:var(--data);font-size:12px;padding:5px 10px;
  border:1px solid var(--line);border-radius:3px;background:var(--card)}

/* the header image an administrator uploads */
.hero{
  border-radius:var(--r);margin-bottom:var(--s6);position:relative;overflow:hidden;
  background-size:cover;background-position:center;
}
.hero__t{
  position:absolute;left:var(--s5);bottom:var(--s4);z-index:1;color:#fff;
  font-family:var(--ui);font-weight:700;font-size:24px;letter-spacing:-.02em;
  text-shadow:0 1px 4px rgba(0,0,0,.45);
}

/* ── 10a. landing ───────────────────────────────────────── */
.land{max-width:var(--maxw);margin:0 auto}
.hero--land{height:230px}
.land__top{text-align:center;padding:var(--s8) 0 var(--s7)}
.land__logo{max-height:60px;width:auto;margin:0 auto var(--s5)}
.land__h{font-size:clamp(32px,5vw,46px);line-height:1.02;letter-spacing:-.035em;margin-bottom:var(--s4)}
.land__tag{font-family:var(--text);font-size:20px;line-height:1.5;color:var(--slate);
  max-width:32ch;margin:0 auto var(--s6)}
.land__cta{display:flex;gap:var(--s3);justify-content:center;flex-wrap:wrap;margin-top:var(--s6)}
.pills--land{margin-bottom:var(--s3)}
.pills--land .pill{font-size:15px;padding:10px 24px;border-width:1.5px}
.land__three{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:var(--s4);margin-bottom:var(--s8)}
.land__card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:var(--s5)}
.land__n{font-family:var(--ui);font-weight:700;font-size:16px;letter-spacing:-.015em;margin-bottom:var(--s2)}
.land__card p{font-size:15.5px;line-height:1.6;color:var(--slate);margin:0}
.land__exams{border-top:1px solid var(--line);padding-top:var(--s6);margin-bottom:var(--s7)}
.land__exams .small{max-width:64ch}
.land__foot{display:flex;gap:var(--s4);align-items:center;flex-wrap:wrap;
  border-top:1px solid var(--line);padding-top:var(--s6)}

/* ── 10b. admin design screen ───────────────────────────── */
.dgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:var(--s3) var(--s4)}
.dfield{margin-bottom:var(--s4)}
.dfield > label{display:block;font-size:13.5px;color:var(--slate);margin-bottom:var(--s2)}
.drow{display:flex;gap:var(--s2);align-items:center}
.dfield input[type=color]{width:44px;height:38px;padding:2px;flex:none;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--r);background:var(--card)}
.dfield input.hex{flex:1;min-width:0;font-family:var(--data);font-size:13.5px}
.dfield input[type=range]{flex:1;accent-color:var(--trace)}
.dval{font-family:var(--data);font-size:12.5px;color:var(--slate);
  min-width:56px;text-align:right;flex:none}
.dfield input.file{font-size:13.5px;margin-right:var(--s2);width:auto}
.thumb{max-width:100%;max-height:150px;border:1px solid var(--line);
  border-radius:var(--r);margin-bottom:var(--s3);background:var(--paper)}

/* ── 10c. responsive ────────────────────────────────────── */
@media(max-width:760px){
  .wrap{padding:var(--s5) var(--s4) var(--s8)}
  .card,.pickbig,.tile{padding:var(--s4)}
  .fix__t,.fix__body{padding-left:var(--s4);padding-right:var(--s4)}
  .grid__head,.grow,.grid__area,.key{padding-left:var(--s4);padding-right:var(--s4)}
  .grid__head,.grow{grid-template-columns:1fr repeat(var(--levels,6),34px)}
  .grow__label{font-size:14px}
  .cell{height:30px}
  .ask{padding:var(--s5) 0 var(--s4)}
  .pill{padding:11px 22px;font-size:15.5px}
  .pills{gap:var(--s2)}
  .land__top{padding:var(--s6) 0 var(--s5)}
  .counted{grid-template-columns:repeat(auto-fit,minmax(96px,1fr))}
  .top__in{gap:var(--s2)}
  .tab{padding:6px 10px;font-size:13.5px}
}
@media(max-width:420px){
  .pills{flex-direction:column;align-items:stretch}
  .pill{text-align:center}
}

/* ── compatibility: an earlier dashboard used these ──────────
   Kept so a partly-updated installation still renders properly
   rather than falling apart into plain text. */
.five{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:var(--s3);margin-bottom:var(--s6)}
.big{display:flex;flex-direction:column;justify-content:flex-end;min-height:150px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4);text-decoration:none;color:inherit;
  transition:border-color .14s,transform .14s,box-shadow .14s}
a.big:hover{border-color:var(--ink);transform:translateY(-3px);box-shadow:0 4px 14px rgba(0,0,0,.06)}
.big__t{display:block;font-family:var(--ui);font-weight:700;font-size:21px;
  letter-spacing:-.02em;margin-bottom:4px}
.big__d{display:block;font-size:13.5px;color:var(--slate);line-height:1.4;margin-bottom:var(--s3)}
.big__n{display:block;margin-top:auto;font-family:var(--data);font-size:11px;color:var(--muted)}
.big--soon{opacity:.45}
.big--soon .big__n{color:var(--mark)}

/* ── panels behind loose text ─────────────────────────────
   Text that is not already inside a card — page headings, ledes,
   the dashboard question, section labels — floats directly on the
   page. That is right on a plain background and unreadable over a
   photograph.

   Raising "Panels behind text" in the Design screen gives each of
   those blocks something to sit on. At zero these rules cost nothing:
   the colour is transparent and the padding is zero, so the layout is
   identical to having no rule at all. */

/* Only when there is a picture behind them. On a plain page the text
   should sit on the page — boxing it there would be clutter. */
.has-bg .wrap > h1,
.has-bg .wrap > .lede,
.has-bg .wrap > .crumb,
.has-bg .wrap > .eyebrow,
.has-bg .ask,
.has-bg .sec > .sec__h,
.has-bg .land__top,
.has-bg .land__exams,
.has-bg .land__foot{
  background:var(--panel);
  border-radius:var(--r);
  padding:var(--panel-pad);
}

/* a heading and its lede read as one block, not two stacked boxes */
.has-bg .wrap > h1{border-radius:var(--r) var(--r) 0 0;padding-bottom:calc(var(--panel-pad) / 2)}
.has-bg .wrap > h1 + .lede{border-radius:0 0 var(--r) var(--r);padding-top:calc(var(--panel-pad) / 2);margin-top:0}
.has-bg .wrap > .crumb{border-radius:var(--r) var(--r) 0 0;padding-bottom:0}
.has-bg .wrap > .crumb + h1{border-radius:0;padding-top:calc(var(--panel-pad) / 2)}

/* the eyebrow above a title belongs to the same block */
.has-bg .wrap > .eyebrow{border-radius:var(--r) var(--r) 0 0;padding-bottom:0}
.has-bg .wrap > .eyebrow + h1{border-radius:0;padding-top:calc(var(--panel-pad) / 2)}

/* the section label sits on its own, so it stays a tab rather than
   stretching the width of the page */
.has-bg .sec > .sec__h{
  display:inline-block;width:auto;
  padding-left:var(--panel-pad);padding-right:var(--panel-pad);
  border-bottom-left-radius:0;border-bottom-right-radius:0;
}

/* when there is a picture, the quiet note under the pills needs more
   help than the rest — it is the smallest and palest thing on screen */
.ask__note{border-radius:var(--r)}

/* ── speaking ────────────────────────────────────────────── */
.sayline{font-family:var(--text);font-size:26px;line-height:1.5;letter-spacing:-.01em}
.sayline .w{font-weight:inherit}
.sayline .w.key{box-shadow:inset 0 -3px 0 var(--gold-bg)}
.sayline .w.lost{background:var(--mark-bg);box-shadow:inset 0 0 0 1.5px var(--mark);
  border-radius:3px;padding:0 3px}
.btn--rec{background:var(--mark);border-color:var(--mark)}
.btn--rec:hover{background:var(--mark);border-color:var(--mark)}
@media(max-width:600px){.sayline{font-size:21px}}

/* ── complete the words ──────────────────────────────────── */
.cloze{font-family:var(--text);font-size:18px;line-height:2.3}
.gap{
  display:inline-block;font-family:var(--text);font-size:17px;
  border:0;border-bottom:2px solid var(--slate);background:var(--line-soft);
  padding:1px 4px;margin:0 1px;border-radius:2px 2px 0 0;min-width:34px;
}
.gap:focus{outline:none;background:var(--trace-bg);border-bottom-color:var(--trace)}
span.gap{border-bottom:0;border-radius:3px}
.gap--right{background:var(--trace-bg);color:var(--trace)}
.gap--ending{background:var(--gold-bg);color:var(--gold)}
.gap--wrong{background:var(--mark-bg);color:var(--mark)}
.gap s{opacity:.55;margin-right:4px}

/* TOEFL presentation wrappers */
.asEmail{border:2px solid var(--ink);border-radius:var(--r);overflow:hidden;max-width:520px}
.asEmail__row{display:grid;grid-template-columns:88px 1fr;border-bottom:1px solid var(--ink)}
.asEmail__k{background:var(--ink);color:var(--paper);padding:8px var(--s3);font-size:14px}
.asEmail__v{padding:8px var(--s3);font-family:var(--data);font-size:13.5px;word-break:break-all}
.asEmail__body{padding:var(--s4);font-family:var(--text);font-size:16px;line-height:1.7}
.asPost{border:2px solid var(--line);border-radius:20px;padding:var(--s3);max-width:400px;background:var(--card)}
.asPost__bar{background:var(--ink);border-radius:12px 12px 0 0;height:34px;margin:-4px -4px var(--s3)}
.asPost__who{display:flex;align-items:center;gap:var(--s2);font-weight:600;margin-bottom:var(--s3)}
.asPost__who i{width:30px;height:30px;border-radius:50%;background:var(--gold-bg);display:block}
.asPost__body{font-family:var(--text);font-size:15.5px;line-height:1.65}
@media(max-width:600px){.cloze{font-size:16.5px;line-height:2.2}}

/* ── CEFR LEVEL, SAID IN WORDS ──────────────────────────────────────
   A letter on its own means nothing to most learners, so level_stack()
   in lib/profile.php prints the word beneath it. Sizes and colours come
   from tokens.css; nothing here introduces either. */
.lvl{display:inline-flex;flex-direction:column;line-height:1.15;text-align:inherit}
.lvl b{font-weight:700;font-style:normal}
.lvl i{font-style:normal;font-size:.72em;font-weight:400;
       color:var(--muted);letter-spacing:.01em;white-space:nowrap;margin-top:1px}

/* In the skills grid the columns are narrow, so the word wraps rather
   than forcing the grid wider than the screen. */
.grid__lvl .lvl i{white-space:normal;font-size:.66em}

/* ── JOIN A CLASS ───────────────────────────────────────────────────
   Closed by default. Most people arrive without a code, and a form
   asking for one they do not have reads as a wall. */
.joinbox{margin:0 0 var(--s5)}
.joinbox summary{cursor:pointer;font-size:14.5px;color:var(--slate);
                 padding:var(--s2) 0;list-style:revert}
.joinbox summary:hover{color:var(--ink)}
.joinbox__f{display:flex;gap:var(--s2);align-items:center;margin-top:var(--s2);flex-wrap:wrap}
.joinbox__f input{font-family:var(--data);text-transform:uppercase;
                  letter-spacing:.18em;max-width:190px;margin:0}

/* ── LANDING: THE LEVEL LADDER ──────────────────────────────────────
   Six steps a visitor can find themselves on before reading anything.
   Built from tokens so it restyles with the site and cannot arrive as a
   broken image. The rise is drawn with padding, not absolute positions,
   so it survives any font size the Design screen chooses. */
.land__note{font-size:14.5px;color:var(--muted);margin:var(--s4) 0 0}

.ladder{margin:var(--s7) 0 var(--s8);text-align:center}
.ladder__lead{font-family:var(--text);font-size:17px;color:var(--slate);margin-bottom:var(--s5)}
.ladder__row{display:flex;gap:var(--s2);align-items:flex-end;justify-content:center;flex-wrap:wrap}
.ladder__step{
  flex:1 1 92px;max-width:150px;
  display:flex;flex-direction:column;gap:2px;
  padding:var(--s3) var(--s2);
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--card);
  /* each step sits a little higher than the one before it */
  margin-bottom:calc(var(--i) * 6px);
}
.ladder__code{font-family:var(--ui);font-weight:700;font-size:17px;letter-spacing:-.01em}
/* Two lines' worth of height whether the word needs it or not. Without
   this, 'Upper intermediate' wraps, its box grows, and the rising line
   the ladder exists to draw develops a kink in the middle. */
.ladder__word{font-family:var(--data);font-size:10.5px;letter-spacing:.04em;color:var(--muted);
  line-height:1.3;min-height:calc(10.5px * 1.3 * 2)}
@media(max-width:560px){
  .ladder__step{margin-bottom:0;flex:1 1 84px}
  .ladder__row{gap:var(--s1)}
}

/* ── PRICING ────────────────────────────────────────────────────────
   One number, large, with everything that qualifies it close by. A price
   a reader has to hunt for reads as a price somebody is hiding. */
.price{text-align:center;padding:var(--s5) 0 var(--s6);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.price__big{font-family:var(--ui);font-weight:700;letter-spacing:-.03em;
  font-size:clamp(40px,7vw,60px);line-height:1.05}
.price__per{font-family:var(--text);font-weight:400;font-size:19px;
  color:var(--slate);letter-spacing:0;margin-left:var(--s2)}
.price__was{font-size:.5em;color:var(--muted);text-decoration:line-through;
  margin-right:var(--s3);font-weight:400}
.price__code{font-family:var(--data);font-size:12.5px;color:var(--muted);margin:var(--s2) 0 0}
.price__code--on{color:var(--trace)}
.price__cur{display:flex;gap:var(--s2);align-items:center;justify-content:center;
  flex-wrap:wrap;margin-top:var(--s5)}
.price__cur select{margin:0;max-width:260px}

/* ── LANGUAGE PICKER ────────────────────────────────────────────────
   Each language written in its own script, because someone who cannot
   read the interface can still recognise 日本語 or العربية. Opens on
   hover and on keyboard focus, so it works without a mouse. */
.langpick{position:relative;display:inline-block}
.langpick__b{background:none;border:0;cursor:pointer;font:inherit}
.langpick__b i{font-size:.7em;opacity:.6;font-style:normal}
.langpick__m{
  position:absolute;top:100%;inset-inline-end:0;z-index:40;
  display:none;min-width:190px;max-height:60vh;overflow-y:auto;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s2) 0;box-shadow:0 6px 24px rgba(0,0,0,.10)
}
.langpick:hover .langpick__m,
.langpick:focus-within .langpick__m{display:block}
.langpick__m a{
  display:flex;align-items:baseline;gap:var(--s2);justify-content:space-between;
  padding:var(--s2) var(--s4);text-decoration:none;color:var(--ink);font-size:15px
}
.langpick__m a:hover,.langpick__m a:focus{background:var(--line-soft)}
.langpick__m a.on{font-weight:700}
.langpick__mt{font-family:var(--data);font-size:9.5px;letter-spacing:.06em;
  color:var(--muted);font-style:normal;text-transform:uppercase;flex:none}

/* ── RIGHT TO LEFT ──────────────────────────────────────────────────
   Most of the layout is flex and grid and flips on its own once dir is
   set on <html>. These are the places that pinned a physical side and
   have to be told. */
[dir="rtl"] .crumb,[dir="rtl"] .land__top,[dir="rtl"] .price{text-align:right}
[dir="rtl"] .land__top,[dir="rtl"] .price,[dir="rtl"] .ladder{text-align:center}
[dir="rtl"] .note,[dir="rtl"] .notice{border-left:0;border-right:3px solid var(--mark)}
[dir="rtl"] .grid__lvl{text-align:center}
[dir="rtl"] .joinbox__f input{letter-spacing:0}

/* ── MONTHLY OR YEARLY ──────────────────────────────────────────────
   Two links, not a toggle switch. A switch hides which state is which
   until you read the label; two options side by side show both prices
   exist and which one you are looking at. */
.planpick{display:flex;gap:var(--s1);justify-content:center;margin:0 0 var(--s5)}
.planpick__o{
  display:flex;align-items:baseline;gap:var(--s2);
  padding:var(--s2) var(--s5);text-decoration:none;color:var(--slate);
  border:1px solid var(--line);border-radius:var(--r);
  font-family:var(--ui);font-size:15px
}
.planpick__o.on{background:var(--ink);color:var(--paper);border-color:var(--ink);font-weight:600}
.planpick__o i{font-family:var(--data);font-size:10.5px;font-style:normal;
  letter-spacing:.05em;color:var(--trace)}
.planpick__o.on i{color:var(--gold)}

/* ── SITE FOOTER ────────────────────────────────────────────────────
   On every page. A privacy policy nobody can find is not one, and a
   payment provider looks for these links before approving an account. */
.foot{border-top:1px solid var(--line);margin-top:var(--s8);padding:var(--s5) var(--s5) var(--s6)}
.foot__in{max-width:var(--maxw);margin:0 auto;display:flex;gap:var(--s4);
  align-items:center;justify-content:space-between;flex-wrap:wrap}
.foot__c{font-size:13.5px;color:var(--muted)}
.foot__n{display:flex;gap:var(--s4);flex-wrap:wrap}
.foot__n a{font-size:13.5px;color:var(--slate);text-decoration:none}
.foot__n a:hover{color:var(--ink);text-decoration:underline}

/* ── LEGAL PAGES ────────────────────────────────────────────────────
   Read, not skimmed: a comfortable measure and real space between
   clauses. Everyone reading these is learning English. */
.legal h2{font-size:19px;margin:0 0 var(--s3)}
.legal .card{margin-bottom:var(--s4)}
.legal p{line-height:1.7}
.legal table{width:100%;font-size:15px}
.legal td,.legal th{padding:var(--s2) var(--s3) var(--s2) 0;vertical-align:top}

/* ── MESSAGES ───────────────────────────────────────────────────────
   A conversation, not a ticket. The learner's own words sit plain and
   ours sit on a tinted ground, so it reads as somebody answering. */
.msg{padding:var(--s3) 0;border-bottom:1px solid var(--line-soft)}
.msg:last-child{border-bottom:0}
.msg--staff{background:var(--trace-bg);margin:0 calc(var(--s5) * -1);
  padding-inline:var(--s5);border-bottom:0}
.msg__who{font-family:var(--ui);font-weight:600;font-size:14px;margin-bottom:var(--s1)}
.msg__at{font-family:var(--data);font-size:11px;color:var(--muted);
  font-weight:400;margin-inline-start:var(--s2)}
.msg__b{font-family:var(--text);line-height:1.65}
.tab--mark{color:var(--mark)}

/* ── A MODULE ───────────────────────────────────────────────────────
   Rail beside body on a wide screen, stacked on a narrow one. The rail
   is navigation, so it comes first in the source and first on a phone —
   a learner on a small screen should not scroll past the whole page to
   find the way to another part of it. */
.mod{display:grid;grid-template-columns:200px 1fr;gap:var(--s6);align-items:start}
.mod__rail{position:sticky;top:var(--s4)}
.mod__railh{font-family:var(--data);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);margin:0 0 var(--s2)}
.mod__r{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s2);
  padding:var(--s2) var(--s3);border-radius:var(--r);text-decoration:none;
  color:var(--slate);font-size:14.5px;line-height:1.35}
a.mod__r:hover{background:var(--line-soft);color:var(--ink)}
.mod__r.on{background:var(--ink);color:var(--paper);font-weight:600}
.mod__r--soon{color:var(--muted);cursor:default}
.mod__r--soon i{font-family:var(--data);font-size:9.5px;font-style:normal;
  letter-spacing:.06em;text-transform:uppercase;opacity:.75;flex:none}

.mod__rec{border-left:3px solid var(--trace)}
.mod__tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
  gap:var(--s3);margin:0 0 var(--s5)}
.mod__t{display:block;padding:var(--s4);background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);text-decoration:none;color:var(--ink)}
a.mod__t:hover{border-color:var(--ink)}
.mod__t.on{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.mod__t--off{opacity:.45}
.mod__tl{font-family:var(--ui);font-weight:600;font-size:15.5px;margin-bottom:var(--s1)}
.mod__td{font-size:13.5px;color:var(--slate);line-height:1.45}

.mod__task{display:flex;align-items:center;justify-content:space-between;gap:var(--s4);
  padding:var(--s3) 0;border-bottom:1px solid var(--line-soft);text-decoration:none;color:var(--ink)}
.mod__task:last-child{border-bottom:0}
.mod__task:hover .mod__taskt{text-decoration:underline}
.mod__taskt{font-family:var(--text);font-size:16px}
.mod__taskm{flex:none;text-align:center}

@media(max-width:820px){
  .mod{grid-template-columns:1fr;gap:var(--s5)}
  .mod__rail{position:static}
  .mod__rail nav{display:flex;flex-wrap:wrap;gap:var(--s1)}
  .mod__r{padding:var(--s2) var(--s3);border:1px solid var(--line)}
}

/* ── THE TEN MODULES, ON THE PRACTISE PAGE ──────────────────────────
   A door each, with what you have done of what exists. An empty one is
   dimmed but still opens — it explains itself rather than looking
   broken, and a dead tile teaches a learner that tiles lie. */
.modgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));
  gap:var(--s3);margin:0 0 var(--s6)}
.modcard{display:flex;flex-direction:column;gap:var(--s1);
  padding:var(--s4);background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);text-decoration:none;color:var(--ink)}
.modcard:hover{border-color:var(--ink)}
.modcard--empty{opacity:.55}
.modcard__l{font-family:var(--ui);font-weight:600;font-size:16px;letter-spacing:-.01em}
.modcard__n{font-family:var(--data);font-size:11.5px;color:var(--muted)}
.modcard__bar{display:block;height:3px;background:var(--line);border-radius:2px;margin-top:var(--s2)}
.modcard__bar i{display:block;height:100%;background:var(--trace);border-radius:2px}

/* ── REVIEW ─────────────────────────────────────────────────────────
   The week ahead as bars, so a heavy day is visible before it arrives
   rather than discovered by opening it. */
.upnext{display:flex;gap:var(--s2);align-items:flex-end}
.upnext__d{flex:1;text-align:center}
.upnext__n{display:block;font-family:var(--ui);font-weight:700;font-size:18px}
.upnext__l{display:block;font-family:var(--data);font-size:10.5px;color:var(--muted);
  letter-spacing:.06em;margin-top:2px}

.wordlist{display:flex;flex-wrap:wrap;gap:var(--s2)}
.wordlist__w{font-family:var(--text);font-size:15.5px;padding:3px 10px;
  border-radius:999px;background:var(--line-soft);cursor:default}
.wordlist__w--known,.wordlist__w--productive{background:var(--gold-bg);
  box-shadow:inset 0 0 0 1px var(--gold)}
.wordlist__w--learning{background:var(--trace-bg)}

/* ── ONE WORD AT A TIME ─────────────────────────────────────────────
   The word large and alone. Nothing else on screen to read while you
   are trying to remember, because anything else to read is an escape
   from trying. */
.rev{text-align:center;padding:var(--s6) var(--s5)}
.rev__n{font-family:var(--data);font-size:11px;letter-spacing:.1em;color:var(--muted)}
.rev__w{font-family:var(--text);font-size:clamp(30px,6vw,44px);margin:var(--s4) 0 var(--s5)}
.rev__g{font-family:var(--text);font-size:18px;color:var(--slate);
  max-width:44ch;margin:0 auto var(--s5);line-height:1.6}
.rev__ask{font-family:var(--ui);font-weight:600;font-size:15px;margin-bottom:var(--s3)}
.rev__btns{display:flex;gap:var(--s2);justify-content:center;flex-wrap:wrap;min-height:42px}
.rev__next{font-family:var(--data);font-size:13px;color:var(--trace);align-self:center}

/* ── CHARTS, DRAWN FROM TOKENS ──────────────────────────────────────
   Bars in CSS rather than a charting library: no external script, no
   content-policy problem, and they restyle with the site. */
.bars{display:flex;gap:var(--s2);align-items:flex-end;height:130px}
.bars__b{flex:1;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;height:100%;gap:var(--s2)}
.bars__b i{display:block;width:100%;max-width:44px;background:var(--trace);
  border-radius:2px 2px 0 0;min-height:2px}
.bars__b span{font-family:var(--data);font-size:10px;color:var(--muted);
  letter-spacing:.04em;white-space:nowrap}
.bars--lvl .bars__b i{background:var(--gold)}

.meter{display:grid;grid-template-columns:112px 1fr 120px;gap:var(--s3);
  align-items:center;padding:var(--s2) 0}
.meter__l{font-family:var(--ui);font-weight:600;font-size:14.5px}
.meter__t{display:block;height:8px;background:var(--line);border-radius:4px;overflow:hidden}
.meter__t i{display:block;height:100%;background:var(--trace)}
.meter__v{font-family:var(--ui);font-weight:600;font-size:14.5px;text-align:right}
.meter__v .small{display:block;font-weight:400}
.meter__thin{color:var(--mark)}
@media(max-width:560px){.meter{grid-template-columns:88px 1fr 92px;gap:var(--s2)}}

/* ── TODAY ──────────────────────────────────────────────────────────
   A short list with a number on each line, so finishing it is visibly
   possible. Nothing is marked overdue, ever. */
.plan__i{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s3) 0;
  border-bottom:1px solid var(--line-soft);text-decoration:none;color:var(--ink)}
.plan__i:last-of-type{border-bottom:0}
.plan__i:hover .plan__l{text-decoration:underline}
.plan__n{flex:none;width:26px;height:26px;border-radius:50%;background:var(--ink);
  color:var(--paper);display:grid;place-items:center;
  font-family:var(--data);font-size:12px;margin-top:2px}
.plan__b{flex:1;min-width:0}
.plan__l{display:block;font-family:var(--ui);font-weight:600;font-size:15.5px}
.plan__w{display:block;font-size:13.5px;color:var(--slate);line-height:1.45;margin-top:2px}
.plan__m{flex:none;font-family:var(--data);font-size:12px;color:var(--muted);margin-top:4px}

.week{display:flex;gap:var(--s2);justify-content:space-between;max-width:340px}
.week__d{text-align:center;flex:1}
.week__l{display:block;font-family:var(--data);font-size:10px;color:var(--muted);letter-spacing:.06em}
.week__o{display:block;font-size:20px;color:var(--line);line-height:1.2}
.week__d.on .week__o{color:var(--trace)}

/* ── direction, for text that is not in the interface language ────────
   The interface direction is set once, on <html>, from the language the
   learner chose. For Arabic, Persian, Urdu and Hebrew that is rtl — and
   an English sentence dropped into an rtl block has its closing full stop
   dragged to the front: ".Sign the form, then take it to the office"
   instead of "Sign the form, then take it to the office." That is every
   passage, question and prompt on the platform, in four of the twenty
   languages. The words stay readable, which is why it never complained.

   Two different problems, so two rules. Membership of each is decided by
   what the text IS, never by who is reading it. */

/* 1. Material that is English by definition — the thing being learned.
      unicode-bidi:isolate matters as much as direction:ltr: without it
      the block still joins the surrounding rtl run and can reorder the
      Arabic beside it. */
#passage, .wd__say, .wd__g, .wd__place, .wd__note,
.q__stem, .opt, .script, .sayline, .cloze,
.asEmail__body, .asPost__body, .rev__w, .rev__g,
.wordlist__w, .mod__taskt, .ph__p, .ph__n, .tk__say {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
}

/* 2. Text somebody typed, in a language nobody declared — a note to
      themselves, a message from their teacher. Forcing ltr here would
      break an Arabic learner's own notes, which is the same bug pointed
      the other way. plaintext is the CSS form of dir="auto": each
      paragraph takes its direction from its first strong character. */
.msg__b, #tasknote textarea {
  unicode-bidi: plaintext;
}

/* APP_CSS_V1_END */
