/* ============================================================
   Shared design language.

   Tokens lifted verbatim from index.html so every generated page is the same
   product as the landing page. index.html keeps its own inline copy for now —
   it is hand-written and works, and rewriting it to import this only to prove
   a point risks breaking a page that is already right.

   Everything below is what the generated pages need and the landing page
   already had: header, footer, buttons, cards, prose, FAQ accordion.
   ============================================================ */

:root{
  --green:#58cc02; --green-dark:#4aa302; --green-deep:#43850a;
  --lime:#a5ed6e; --lime-pale:#d7ffb8;
  --blue:#1cb0f6; --blue-dark:#1899d6; --blue-pale:#ddf4ff; --navy:#042c60;

  --eel:#4b4b4b; --eel-dark:#3c3c3c; --wolf:#777777; --hare:#afafaf;
  --swan:#e5e5e5; --snow:#f7f7f7; --white:#ffffff;

  --bee:#ffc800; --bee-dark:#e6a800; --fox:#ff9600;
  --cardinal:#ff4b4b; --beetle:#ce82ff;

  --font:'Nunito',ui-rounded,'SF Pro Rounded','Segoe UI',system-ui,-apple-system,sans-serif;

  --sp-8:8px; --sp-12:12px; --sp-16:16px; --sp-20:20px; --sp-24:24px; --sp-32:32px;
  --sp-40:40px; --sp-48:48px; --sp-64:64px; --sp-80:80px; --sp-96:96px;

  --page:1100px; --gap:100px; --r-btn:16px; --r-card:16px;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:96px;-webkit-text-size-adjust:100%}
body{margin:0;background:var(--white);color:var(--eel);font-family:var(--font);
  font-weight:600;font-size:16px;line-height:1.6;letter-spacing:.01em;
  -webkit-font-smoothing:antialiased;overflow-x:hidden}
img,svg{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
.wrap{max-width:var(--page);margin:0 auto;padding:0 var(--sp-24)}
section{scroll-margin-top:96px}

/* ---------- header ---------- */
.site-head{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(1.4) blur(8px);border-bottom:1px solid var(--swan)}

/* The header gets its own width, wider than --page.
   Prose reads best at 1100px, but this bar carries a wordmark, six nav items,
   a sign-in and a primary CTA. Capping it at the prose width left no room, so
   labels wrapped onto a second line and the bar grew to double height on
   /practice, /tasks and anywhere the wording ran long. The content column is
   unchanged; only the chrome is allowed to breathe. */
.site-head .in{max-width:1320px;margin:0 auto;padding:var(--sp-12) var(--sp-32);
  display:flex;align-items:center;gap:var(--sp-24)}
.logo{display:flex;align-items:center;gap:10px;font-weight:900;font-size:19px;
  color:var(--green);white-space:nowrap;flex:0 0 auto}

.nav{display:flex;align-items:center;gap:var(--sp-24);margin-left:auto;flex:0 1 auto}
/* Nothing in the bar may wrap. A nav item broken across two lines is the most
   obvious possible sign of a broken layout, and it was happening on every page
   whose labels ran long. */
.nav > *{white-space:nowrap;flex:0 0 auto}
.navlink{font-size:15px;font-weight:700;color:var(--wolf);white-space:nowrap}
.navlink:hover,.navlink[aria-current=page]{color:var(--eel-dark)}
@media(max-width:1080px){.nav .navlink{display:none}}

/* Sign in is a real button from the system, not a bespoke pill.
   It used to be a hand-rolled 999px outline at 14px with its own padding,
   which is exactly why it read as a different species from every other control
   on the site. `btn btn-ghost btn-sm` gives it the same radius, weight and
   press behaviour as everything else. It keeps `display:inline-flex` past the
   breakpoint above because a returning user needs it at every width and the
   collapsed nav leaves nowhere else to look. */
.site-head .nav .btn-ghost{display:inline-flex !important;color:var(--eel);
  border-color:var(--swan)}
.site-head .nav .btn-ghost:hover{color:var(--eel-dark);border-color:var(--hare);
  background:var(--snow)}
.site-head .nav .btn-ghost[aria-current=page]{color:var(--green-deep);border-color:var(--green)}

@media(max-width:1080px){.nav{gap:var(--sp-12)}}
@media(max-width:620px){
  .site-head .in{gap:var(--sp-12);padding-left:var(--sp-16);padding-right:var(--sp-16)}
  .site-head .logo .brand-text{display:none}
  .site-head .nav .btn{padding-left:13px;padding-right:13px;font-size:12.5px}
}


/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  border:0;border-radius:var(--r-btn);font:inherit;font-weight:800;letter-spacing:.6px;
  text-transform:uppercase;font-size:14px;padding:14px 24px;cursor:pointer;
  transition:filter .12s,transform .06s}
.btn-primary{background:var(--green);color:#fff;
  border:2px solid var(--green);box-shadow:0 4px 0 var(--green-dark)}
.btn-primary:hover{filter:brightness(1.05)}
.btn-primary:active{transform:translateY(3px);box-shadow:0 1px 0 var(--green-dark)}
.btn-blue{background:var(--blue);color:#fff;
  border:2px solid var(--blue);box-shadow:0 4px 0 var(--blue-dark)}
.btn-blue:active{transform:translateY(3px);box-shadow:0 1px 0 var(--blue-dark)}
/* Matched geometry: both weights carry a 2px border and a 4px lift below the
   box, so a primary and a ghost side by side are the same height and share a
   baseline. The ghost previously put its 4px inside the border box, making it
   sit 4px shallower than the primary next to it. */
.btn-ghost{background:#fff;color:var(--blue);
  border:2px solid var(--swan);box-shadow:0 4px 0 var(--swan)}
.btn-ghost:active{transform:translateY(3px);box-shadow:0 1px 0 var(--swan)}
.btn-ghost:hover{background:var(--snow)}
.btn-sm{padding:9px 16px;font-size:13px}
.btn-lg{padding:16px 32px;font-size:15px}
.btn-block{width:100%}

/* ---------- page furniture ---------- */
.page-head{padding:var(--sp-64) 0 var(--sp-40);text-align:center}
.page-head h1{font-size:clamp(30px,5vw,46px);font-weight:900;color:var(--eel-dark);
  margin:0 0 var(--sp-16);line-height:1.15;letter-spacing:-.02em}
.page-head p{max-width:640px;margin:0 auto;color:var(--wolf);font-size:17px}
.kicker{display:inline-block;font-size:12px;font-weight:800;letter-spacing:1.4px;
  text-transform:uppercase;color:var(--green-deep);background:var(--lime-pale);
  padding:5px 12px;border-radius:99px;margin-bottom:var(--sp-16)}
.kicker.blue{color:var(--blue-dark);background:var(--blue-pale)}

h2{font-size:clamp(22px,3.4vw,30px);font-weight:900;color:var(--eel-dark);
  margin:0 0 var(--sp-16);letter-spacing:-.01em}
h3{font-size:19px;font-weight:800;color:var(--eel-dark);margin:0 0 var(--sp-8)}

/* 720px inside an 1100px wrap left a narrow ribbon of text with big empty
   gutters on both sides. 880px keeps a comfortable measure (~85 characters at
   16px) while filling the section properly. Blocks that carry their own
   layout — tables, card grids, widgets, illustrations — break out to the full
   wrap, because those were the worst offenders when squeezed. */
/* Full wrap width, so a prose section lines up with the split sections
   above and below it instead of sitting as a narrower centred column.
   Paragraphs keep a readable measure via their own cap below — everything
   structural (tables, timelines, steps, cards) spans the whole width. */
.prose{max-width:none;margin:0}
.prose > p,
.prose > ul,
.prose > ol,
.prose > h2,
.prose > h3,
.prose > .callout,
.prose > .pull{max-width:78ch}
.prose > .sec-head{max-width:680px}
.prose > .table-wrap,
.prose > .grid,
.prose > .widget,
.prose > .steps,
.prose > .timeline,
.prose > .dd,
.prose > .stats,
.prose > svg,
.prose > .cmp{max-width:none}
.prose p{margin:0 0 var(--sp-16)}
.prose h2{margin-top:var(--sp-48)}
.prose h3{margin-top:var(--sp-32)}
.prose ul,.prose ol{margin:0 0 var(--sp-16);padding-left:22px}
.prose li{margin-bottom:8px}
.prose a{color:var(--blue-dark);font-weight:700;text-decoration:underline;
  text-underline-offset:3px}
/* A button inside prose is a button, not a link. Without this the .prose a
   rule paints .btn text blue and underlines it, which looked broken. */
.prose a.btn{text-decoration:none}
.prose a.btn-primary,.prose a.btn-blue{color:#fff}
.prose a.btn-ghost{color:var(--blue)}
.prose a.card{text-decoration:none;color:inherit;font-weight:600}
.prose a.card h3{color:var(--eel-dark)}
.prose strong{color:var(--eel-dark);font-weight:800}
/* A lone CTA at the end of a prose block reads as a stray link when it is
   left-aligned under a paragraph. */
.prose > p.cta-p{text-align:center;margin-top:var(--sp-32)}

/* Every top-level section gets vertical rhythm, not just the tinted ones.
   .band used to be the only thing with padding, so a plain <section> sat
   flush against the tinted block above it and the kicker collided with the
   boundary. .band is now purely a background. */
main > section:not(.page-head):not(.panel){padding:var(--sp-64) 0}
.band{padding:var(--sp-64) 0}
.band.snow{background:var(--snow)}
.band.blue{background:var(--blue-pale)}

.grid{display:grid;gap:var(--sp-24)}
@media(min-width:700px){.grid.two{grid-template-columns:repeat(2,1fr)}}
@media(min-width:900px){.grid.three{grid-template-columns:repeat(3,1fr)}}

.card{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;
  border-radius:var(--r-card);padding:var(--sp-24)}
.card p{color:var(--wolf);font-size:15px;margin:0}
/* Grid cards already stretch to the tallest in the row, but their contents did
   not: under a shorter blurb the button floated up, so a row of three CTAs sat
   at three different heights. Column layout with the action pushed to the
   bottom lines them up whatever the copy does. */
.grid > .card{display:flex;flex-direction:column;align-items:flex-start}
/* align-items:flex-start is load-bearing. A flex column stretches its children
   across the cross axis by default, which turned the kicker pill into a
   full-width bar. Children that genuinely want the full width ask for it. */
.grid > .card > .btn-block{align-self:stretch;margin-top:auto}
.grid > .card > p{margin-bottom:var(--sp-16)}
.card .kicker{margin-bottom:10px}

table.data{width:100%;border-collapse:collapse;font-size:15px}
table.data th{text-align:left;font-size:12px;letter-spacing:1px;text-transform:uppercase;
  color:var(--hare);padding:0 12px 10px;font-weight:800}
table.data td{padding:12px;border-top:1px solid var(--swan)}
table.data tr:hover td{background:var(--snow)}

/* ---------- FAQ accordion ---------- */
details.faq{border-bottom:1px solid var(--swan);padding:var(--sp-16) 0}
details.faq summary{list-style:none;cursor:pointer;font-weight:800;color:var(--eel-dark);
  font-size:17px;display:flex;gap:12px;align-items:flex-start}
details.faq summary::-webkit-details-marker{display:none}
details.faq summary::after{content:'+';margin-left:auto;color:var(--hare);
  font-weight:900;font-size:22px;line-height:1;transition:transform .18s}
details.faq[open] summary::after{content:'−'}
details.faq .a{color:var(--wolf);font-size:15px;padding-top:var(--sp-12);max-width:70ch}
details.faq .a p{margin:0 0 10px}

/* ---------- footer ---------- */
.site-foot{background:var(--snow);border-top:1px solid var(--swan);
  padding:var(--sp-64) 0 var(--sp-40);margin-top:var(--sp-96)}
.foot-grid{display:grid;gap:var(--sp-32)}
@media(min-width:760px){.foot-grid{grid-template-columns:2fr 1fr 1fr 1fr}}
.site-foot h4{font-size:12px;letter-spacing:1.2px;text-transform:uppercase;
  color:var(--hare);margin:0 0 var(--sp-12);font-weight:800}
.site-foot ul{list-style:none;margin:0;padding:0}
.site-foot li{margin-bottom:10px}
.site-foot a{font-size:14px;color:var(--wolf);font-weight:700}
.site-foot a:hover{color:var(--eel-dark)}
.foot-legal{border-top:1px solid var(--swan);margin-top:var(--sp-40);
  padding-top:var(--sp-24);font-size:12px;color:var(--hare);line-height:1.7;font-weight:600}

/* ============================================================
   Illustrations, layout blocks and widgets.

   Rule of thumb behind all of it: a section should give the eye somewhere to
   land every screen or so. Long pages are fine; long undifferentiated columns
   are not.
   ============================================================ */

.illus{width:100%;height:auto}
.illus.dial{max-width:260px}
.illus.task-art{max-width:520px}
.illus.ladder,.illus.graph,.illus.diagram{max-width:100%}

/* reveal-on-scroll; site.js adds .in. No JS => everything visible. */
/* Reveal-on-scroll.

   Every hidden-until-revealed state is gated behind html.js, which an inline
   script in <head> sets. Without that gate the default state of these rules
   is invisible, so any page where site.js is slow, blocked or below the fold
   shows a half-drawn graphic — the score dial rendered as two disconnected
   round line-caps, which reads as a broken image rather than as an animation
   that has not started. Visible is the safe default; motion is the
   enhancement. */
.rv,.rung{transition:opacity .5s ease,transform .5s cubic-bezier(.2,.7,.3,1)}
.rung{transition-delay:calc(var(--i) * 70ms)}

html.js .rv:not(.in){opacity:0;transform:translateY(16px)}
html.js .illus:not(.in) .rung{opacity:0;transform:translateY(14px)}

@media(prefers-reduced-motion:reduce){
  html.js .rv:not(.in),
  html.js .illus:not(.in) .rung{opacity:1;transform:none}
  .rv,.rung{transition:none}
}

/* ---------- section heads ---------- */
.sec-head{text-align:center;max-width:680px;margin:0 auto var(--sp-40)}
.sec-head .kicker{margin:0 0 var(--sp-12)}
.sec-head h2,.prose .sec-head h2{margin-top:0}
.prose .sec-head{margin-top:0}
/* Ample space ABOVE a section heading that follows content (it had 0, so
   headers sat jammed against the paragraph above them and floated 40px from
   their own content — the reverse of the right hierarchy). */
.prose > * + .sec-head{margin-top:52px}
.sec-head .sec-sub{color:var(--wolf);font-size:17px;margin:0}
.sec-head.left{text-align:left;margin-left:0}

/* ---------- split: text beside picture ---------- */
.split{display:grid;gap:var(--sp-40);align-items:center;margin:var(--sp-48) 0}
.page-head + section .split:first-child,
section:first-child .split{margin-top:0}
@media(min-width:860px){
  .split{grid-template-columns:1fr 1fr;gap:var(--sp-64)}
  .split.flip .split-text{order:2}
}
.split-text h2,.split-text h3{margin-top:0}
.split-text p{color:var(--wolf);margin:0 0 var(--sp-16)}
.split-text ul{margin:0 0 var(--sp-16);padding-left:20px;color:var(--wolf)}
.split-text li{margin-bottom:8px}
.split-art{display:flex;justify-content:center}

/* ---------- callout ---------- */
.callout{display:flex;gap:14px;align-items:flex-start;border-radius:16px;
  padding:var(--sp-16) var(--sp-24);margin:var(--sp-24) 0;font-size:15px;
  border:2px solid;border-bottom-width:4px}
.callout strong{display:block;margin-bottom:4px;font-size:16px}
.callout p{margin:0 0 8px}.callout p:last-child{margin:0}
.callout.green{background:var(--lime-pale);border-color:#b6e88a;color:#3f6d18}
.callout.green strong{color:var(--green-deep)}
.callout.blue{background:var(--blue-pale);border-color:#a9dffa;color:#0f6e9c}
.callout.blue strong{color:var(--blue-dark)}
.callout.amber{background:#fff6d6;border-color:#ffe08a;color:#8a6300}
.callout.amber strong{color:#a37400}
.callout.red{background:#ffecec;border-color:#ffc4c4;color:#a33}
.callout.red strong{color:var(--cardinal)}
.callout.violet{background:#f3e8ff;border-color:#e2c9f5;color:#6f3a9e}
.callout.violet strong{color:#8236c4}
.callout-ico{font-size:22px;line-height:1.2}

/* ---------- numbered steps with a rail ---------- */
.steps{list-style:none;counter-reset:s;margin:var(--sp-32) 0;padding:0;position:relative}
.steps li{counter-increment:s;position:relative;padding:0 0 var(--sp-32) 62px}
.steps li::before{content:counter(s);position:absolute;left:0;top:0;width:42px;height:42px;
  border-radius:50%;background:var(--green);color:#fff;font-weight:900;font-size:18px;
  display:grid;place-items:center;box-shadow:0 3px 0 var(--green-dark)}
.steps li::after{content:'';position:absolute;left:20px;top:50px;bottom:6px;width:3px;
  background:var(--swan);border-radius:2px}
.steps li:last-child{padding-bottom:0}
.steps li:last-child::after{display:none}
.steps h3{margin:8px 0 6px}
.steps p{margin:0;color:var(--wolf);font-size:15px}

/* ---------- stat strip ---------- */
.stats{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--sp-16);margin:var(--sp-32) 0}
@media(min-width:760px){.stats{grid-template-columns:repeat(4,1fr)}}
/* Inside a split the strip only has half the page, so four across is too
   narrow and every label wraps. Two-by-two fits. */
.split-text .stats{grid-template-columns:repeat(2,1fr);margin-top:0}
.split-text .stat{padding:var(--sp-16) var(--sp-12)}
.stat{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;border-radius:16px;
  padding:var(--sp-24) var(--sp-16);text-align:center}
.stat b{display:block;font-size:30px;font-weight:900;color:var(--green-deep);line-height:1.1;
  hyphens:none;overflow-wrap:break-word}
.stat b.md{font-size:21px;line-height:1.2}
.stat b.sm{font-size:16px;line-height:1.3}
.stat span{display:block;margin-top:6px;font-size:13px;color:var(--wolf);font-weight:700}

/* ---------- cards ---------- */
.card-link{display:block;transition:border-color .18s ease}
.card-link:hover{border-color:var(--hare)}
.card-ico{font-size:26px;margin-bottom:10px;line-height:1}
.card-foot{display:inline-block;margin-top:12px;font-size:13px;font-weight:800;
  color:var(--blue);letter-spacing:.4px}
.card svg.illus{margin-bottom:var(--sp-16)}

/* ---------- tables ---------- */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:var(--sp-24) 0;
  border:2px solid var(--swan);border-bottom-width:4px;border-radius:16px;background:#fff}
.table-wrap table.data{margin:0;min-width:520px}
.table-wrap th{padding:14px 16px 12px;background:var(--snow)}
.table-wrap td{padding:14px 16px}
table.data caption{caption-side:bottom;padding:12px 16px;font-size:13px;color:var(--hare);
  text-align:left;font-weight:600}
table.data tr.hit td{background:var(--lime-pale)}

/* ---------- do / don't ---------- */
.dd{display:grid;gap:var(--sp-24);margin:var(--sp-32) 0}
@media(min-width:760px){.dd{grid-template-columns:1fr 1fr}}
.dd-col{border-radius:16px;padding:var(--sp-24);border:2px solid;border-bottom-width:4px}
.dd-col h3{margin:0 0 12px;font-size:16px;letter-spacing:.5px;text-transform:uppercase}
.dd-col ul{margin:0;padding-left:20px}
.dd-col li{margin-bottom:10px;font-size:15px}
.dd-col li:last-child{margin-bottom:0}
.dd-col.do{background:var(--lime-pale);border-color:#b6e88a}
.dd-col.do h3{color:var(--green-deep)}
.dd-col.dont{background:#ffecec;border-color:#ffc4c4}
.dd-col.dont h3{color:var(--cardinal)}

/* ---------- pull quote ---------- */
.pull{margin:var(--sp-32) 0;padding:var(--sp-24) var(--sp-32);border-left:6px solid var(--green);
  background:var(--snow);border-radius:0 16px 16px 0}
.pull blockquote{margin:0;font-size:19px;font-weight:700;color:var(--eel-dark);line-height:1.5}
.pull figcaption{margin-top:10px;font-size:13px;color:var(--hare);font-weight:700}

/* ---------- timeline ---------- */
.timeline{list-style:none;margin:var(--sp-32) 0;padding:0}
.timeline li{display:grid;grid-template-columns:96px 1fr;gap:var(--sp-16);
  padding-bottom:var(--sp-24);position:relative}
.timeline li::after{content:'';position:absolute;left:104px;top:26px;bottom:0;width:3px;
  background:var(--swan)}
.timeline li:last-child::after{display:none}
.tl-time{font-size:13px;font-weight:900;color:var(--blue-dark);background:var(--blue-pale);
  border-radius:99px;padding:5px 10px;text-align:center;height:fit-content}
.timeline h3{margin:2px 0 4px;font-size:17px}
.timeline p{margin:0;color:var(--wolf);font-size:15px}
@media(max-width:600px){.timeline li{grid-template-columns:1fr}.timeline li::after{display:none}
  .tl-time{justify-self:start}}

/* ============================================================
   Widgets
   ============================================================ */
.widget{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;
  border-radius:20px;padding:var(--sp-24);margin:var(--sp-32) 0}
.widget .wd-head{display:flex;align-items:center;gap:12px;margin-bottom:var(--sp-16)}
.widget .wd-head .kicker{margin:0}
.wd-hint,.wd-note,.ex-note{font-size:13px;color:var(--hare);font-weight:600;margin:12px 0 0}

/* score explorer */
.explorer .ex-head{display:flex;align-items:center;gap:var(--sp-24);flex-wrap:wrap;
  margin-bottom:var(--sp-16)}
.ex-score{display:flex;align-items:baseline;gap:10px}
.ex-num{font-size:52px;font-weight:900;color:var(--eel-dark);line-height:1}
.ex-cefr{font-size:15px;font-weight:900;color:#fff;background:var(--green);
  padding:5px 12px;border-radius:99px;letter-spacing:1px}
.ex-means{font-size:15px;color:var(--wolf);font-weight:700;max-width:44ch;display:block}
.ex-range{width:100%;-webkit-appearance:none;appearance:none;height:16px;border-radius:99px;
  background:linear-gradient(90deg,var(--swan),var(--lime),var(--green));outline:none;margin:8px 0}
.ex-range::-webkit-slider-thumb{-webkit-appearance:none;width:34px;height:34px;border-radius:50%;
  background:#fff;border:5px solid var(--green);cursor:grab;box-shadow:0 2px 6px rgba(0,0,0,.18)}
.ex-range::-moz-range-thumb{width:28px;height:28px;border-radius:50%;background:#fff;
  border:5px solid var(--green);cursor:grab}
.ex-range:active::-webkit-slider-thumb{cursor:grabbing;transform:scale(1.08)}
.ex-scale{display:flex;justify-content:space-between;font-size:12px;color:var(--hare);
  font-weight:800}
.ex-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:var(--sp-24)}
.ex-card{background:var(--snow);border-radius:14px;padding:14px;text-align:center}
.ex-card span{display:block;font-size:11px;letter-spacing:.8px;text-transform:uppercase;
  color:var(--hare);font-weight:800}
.ex-card b{display:block;margin-top:6px;font-size:22px;font-weight:900;color:var(--eel-dark)}
.ex-fallback{margin-top:var(--sp-16)}
.ex-fallback summary{cursor:pointer;font-weight:800;font-size:14px;color:var(--blue-dark)}
@media(max-width:560px){.ex-cards{grid-template-columns:1fr}}

/* word demo */
.wd-progress{flex:1;height:10px;background:var(--swan);border-radius:99px;overflow:hidden}
.wd-progress i{display:block;height:100%;width:0;background:var(--green);border-radius:99px;
  transition:width .25s}
.wd-count{font-size:13px;font-weight:800;color:var(--hare)}
.wd-stage{text-align:center;padding:var(--sp-16) 0}
.wd-word{font-size:clamp(30px,7vw,46px);font-weight:900;color:var(--eel-dark);
  letter-spacing:-.01em;margin-bottom:var(--sp-24);min-height:1.2em}
.wd-word.right{color:var(--green-deep)}
.wd-word.wrong{color:var(--cardinal);text-decoration:line-through}
.wd-btns{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
.wd-btns .btn{min-width:150px}
.wd-done{text-align:center;padding:var(--sp-16) 0}
.wd-score{display:block;font-size:44px;font-weight:900;color:var(--green-deep)}
.wd-verdict{color:var(--wolf);margin:8px 0 var(--sp-16);font-size:15px}

/* read & complete demo */
.cd-text{font-size:18px;line-height:2.6;color:var(--eel-dark);font-weight:700}
.cd-word{white-space:nowrap}
.cd-seen{border-bottom:2px solid var(--swan)}
.cd-in{font:inherit;font-size:18px;font-weight:700;color:var(--blue-dark);border:0;
  border-bottom:2.5px solid var(--blue);background:var(--blue-pale);border-radius:4px 4px 0 0;
  padding:0 3px;min-width:2ch;outline:none;
  /* Without an explicit line-height and baseline alignment the input's own
     box is taller than the surrounding text and it rides up over the line
     above — which is what made the demo look broken. */
  line-height:1.4;height:1.5em;vertical-align:baseline;box-sizing:content-box}
.cd-in:focus{background:#c9ecfd}
.cd-in.right{color:var(--green-deep);border-bottom-color:var(--green);background:var(--lime-pale)}
.cd-in.wrong{color:var(--cardinal);border-bottom-color:var(--cardinal);background:#ffecec}
.cd-actions{display:flex;gap:12px;margin-top:var(--sp-16);flex-wrap:wrap}
.cd-count{margin-left:auto;font-size:13px;font-weight:800;color:var(--hare)}

/* planner */
.pl-controls{display:grid;gap:var(--sp-16);margin-bottom:var(--sp-24)}
@media(min-width:640px){.pl-controls{grid-template-columns:repeat(3,1fr)}}
.pl-controls label{display:block;font-size:12px;font-weight:800;letter-spacing:.6px;
  text-transform:uppercase;color:var(--hare)}
/* Native select chrome varies by platform and put the arrow hard against the
   right edge with no padding. Stripping the appearance and drawing our own
   chevron gives one consistent control with room to breathe. */
.pl-controls select{display:block;width:100%;margin-top:6px;font:inherit;font-weight:800;
  font-size:16px;color:var(--eel-dark);padding:12px 44px 12px 14px;border-radius:14px;
  border:2px solid var(--swan);border-bottom-width:4px;background:#fff;cursor:pointer;
  -webkit-appearance:none;-moz-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2377777f' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center;background-size:18px}
.pl-controls select:hover{border-color:var(--hare)}
.pl-controls select:focus{outline:none;border-color:var(--blue)}
.pl-out{background:var(--snow);border-radius:16px;padding:var(--sp-24)}
.pl-out .pl-big{font-size:26px;font-weight:900;color:var(--green-deep);margin:0 0 8px}
.pl-out p{margin:0 0 10px;font-size:15px;color:var(--wolf)}
.pl-out ul{margin:12px 0 0;padding-left:20px;font-size:15px}
.pl-out li{margin-bottom:8px}

/* checklist */
.checklist .ck-head{display:flex;align-items:center;gap:12px;font-size:13px;font-weight:800;
  color:var(--hare);margin-bottom:var(--sp-16)}
.ck-done{font-size:20px;color:var(--green-deep)}
.ck-bar{flex:1;height:10px;background:var(--swan);border-radius:99px;overflow:hidden}
.ck-bar i{display:block;height:100%;width:0;background:var(--green);transition:width .3s}
.checklist ul{list-style:none;margin:0;padding:0}
.checklist li{border-top:1px solid var(--swan)}
.checklist li:first-child{border-top:0}
.checklist label{display:flex;gap:14px;align-items:flex-start;padding:14px 0;cursor:pointer;
  font-size:15px}
.checklist input{appearance:none;-webkit-appearance:none;flex:0 0 24px;width:24px;height:24px;
  border:2.5px solid var(--swan);border-radius:8px;cursor:pointer;margin:0;position:relative;
  transition:background .15s,border-color .15s}
.checklist input:checked{background:var(--green);border-color:var(--green-dark)}
.checklist input:checked::after{content:'';position:absolute;left:7px;top:2px;width:6px;height:12px;
  border:solid #fff;border-width:0 3px 3px 0;transform:rotate(45deg)}
.checklist input:checked+span{color:var(--hare);text-decoration:line-through}

/* ---------- in-page contents ---------- */
.toc{background:var(--snow);border-radius:16px;padding:var(--sp-24);margin:var(--sp-32) 0}
.toc h2{font-size:13px!important;letter-spacing:1.2px;text-transform:uppercase;
  color:var(--hare);margin:0 0 12px!important}
.toc ol{margin:0;padding-left:20px;columns:2;column-gap:32px}
.toc li{margin-bottom:8px;font-size:15px;break-inside:avoid}
.toc a{color:var(--blue-dark);font-weight:700}
.toc a:hover{text-decoration:underline}
@media(max-width:640px){.toc ol{columns:1}}

/* ---------- next / prev ---------- */
.pager{display:grid;gap:var(--sp-16);margin:var(--sp-48) 0 0}
@media(min-width:640px){.pager{grid-template-columns:1fr 1fr}}
.pager a{border:2px solid var(--swan);border-bottom-width:4px;border-radius:16px;
  padding:var(--sp-16) var(--sp-24);display:block}
.pager a:hover{border-color:var(--hare)}
.pager span{display:block;font-size:11px;letter-spacing:1px;text-transform:uppercase;
  color:var(--hare);font-weight:800;margin-bottom:4px}
.pager b{font-size:16px;font-weight:800;color:var(--eel-dark)}
.pager .next{text-align:right}

/* ---------- CTA band ---------- */
/* ---------- closing CTA ----------
   Was a flat tinted rectangle with centred text and a small graphic tacked
   underneath. Rebuilt as a composition: copy and button hold the left column,
   a large illustration owns the right, and the whole thing sits on an
   elevated card. The children are siblings in the markup (h2, p, a, .cta-art)
   so the columns are assembled with named grid areas rather than a wrapper. */
.cta-band{
  background:var(--lime-pale);
  border-radius:28px;
  padding:var(--sp-48);
  margin:var(--sp-80) 0 0;
  display:grid;
  gap:var(--sp-24) var(--sp-48);
  align-items:center;
  grid-template-areas:'art' 'h' 'p' 'b';
  justify-items:center;
  text-align:center;
  box-shadow:0 10px 0 #c6e8a2;
}
.cta-band h2{grid-area:h;margin:0;font-size:clamp(24px,3.2vw,34px);color:var(--green-deep)}
.cta-band p{grid-area:p;margin:0;color:#42731c;font-size:17px;max-width:46ch}
.cta-band > .btn{grid-area:b}
.cta-band .cta-art{grid-area:art;margin:0;width:100%;max-width:420px}

@media(min-width:820px){
  .cta-band{
    grid-template-columns:1fr .85fr;
    grid-template-areas:'h art' 'p art' 'b art';
    justify-items:start;
    text-align:left;
    gap:var(--sp-16) var(--sp-48);
    padding:var(--sp-64);
  }
  .cta-band .cta-art{max-width:none;justify-self:end}
  .cta-band > .btn{margin-top:var(--sp-16)}
}

/* ---------- sample report ---------- */
.rep-hero-split{display:grid;gap:var(--sp-24);align-items:center;justify-items:center}
@media(min-width:700px){.rep-hero-split{grid-template-columns:1fr auto;justify-items:start}}
.rep-dial{width:100%;max-width:240px;justify-self:center}
.rep-art{margin:var(--sp-32) auto;max-width:760px}
.rep-art svg{width:100%;height:auto}

/* ============================================================
   Score report dashboard.

   A report, not an article: sticky sidebar with the headline number and
   section nav, panels of cards in the main column. Deliberately different
   furniture from the content pages so it reads as a document you were issued
   rather than a page you browsed to.
   ============================================================ */

.sample-strip{background:var(--bee);color:#4a3800;font-size:14px;font-weight:700;
  padding:10px var(--sp-24);text-align:center}
.sample-strip strong{font-weight:900}
.sample-strip a{color:#4a3800;text-decoration:underline;font-weight:800}

.dash{max-width:1240px;margin:0 auto;padding:var(--sp-32) var(--sp-24) 0;
  display:grid;gap:var(--sp-32);align-items:start}
@media(min-width:1000px){.dash{grid-template-columns:270px 1fr;gap:var(--sp-40)}}

/* ---------- sidebar ---------- */
@media(min-width:1000px){.dash-side{position:sticky;top:88px}}
.ds-card{background:var(--eel-dark);color:#fff;border-radius:20px;padding:var(--sp-24);
  text-align:center}
.ds-label{font-size:11px;letter-spacing:1.4px;text-transform:uppercase;color:#b9b9b9;
  font-weight:800}
.ds-score{font-size:64px;font-weight:900;line-height:1.05;margin-top:6px}
.ds-score small{font-size:20px;color:#9c9c9c;font-weight:800}
.ds-cefr{display:inline-block;background:var(--green);color:#fff;font-size:12px;
  font-weight:900;letter-spacing:1px;padding:5px 12px;border-radius:99px;margin-top:8px}
.ds-range{font-size:13px;color:#c9c9c9;margin:12px 0 0;font-weight:600}
.ds-range b{color:#fff}

.ds-nav{margin-top:var(--sp-24);display:flex;flex-direction:column;gap:2px}
.ds-nav a{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:12px;
  font-size:15px;font-weight:800;color:var(--wolf)}
.ds-nav a span{width:22px;height:22px;border-radius:50%;background:var(--swan);
  color:var(--wolf);font-size:12px;font-weight:900;display:grid;place-items:center;flex:0 0 22px}
.ds-nav a:hover{background:var(--snow);color:var(--eel-dark)}
.ds-nav a:hover span,.ds-nav a.on span{background:var(--green);color:#fff}
.ds-nav a.on{background:var(--lime-pale);color:var(--green-deep)}

.ds-actions{margin-top:var(--sp-24);display:flex;flex-direction:column;gap:10px}
.ds-actions .btn:disabled{opacity:.45;cursor:not-allowed}
.ds-note{font-size:12px;color:var(--hare);text-align:center;margin:2px 0 0;font-weight:600}

/* ---------- panels ---------- */
.dash-main{min-width:0}
.panel{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;
  border-radius:20px;padding:var(--sp-32);margin-bottom:var(--sp-24)}
.panel > h2{margin:0 0 6px;font-size:clamp(20px,2.6vw,26px)}
.panel-sub{color:var(--wolf);font-size:15px;margin:0 0 var(--sp-24)}
@media(max-width:600px){.panel{padding:var(--sp-24) var(--sp-16)}}

/* ---------- 1. score ---------- */
.score-hero{display:grid;gap:var(--sp-24);align-items:center;margin-top:var(--sp-16)}
@media(min-width:720px){.score-hero{grid-template-columns:250px 1fr;gap:var(--sp-32)}}
.score-dial svg{width:100%;max-width:250px;margin:0 auto}
.say-big{font-size:22px;font-weight:800;color:var(--eel-dark);margin:0 0 10px}
.say-big b{color:var(--green-deep)}
.score-say p{color:var(--wolf);margin:0 0 10px;font-size:15px}
.say-small{font-size:13px!important;color:var(--hare)!important}

.opens{margin-top:var(--sp-32);background:var(--snow);border-radius:16px;padding:var(--sp-24)}
.opens-label{font-size:11px;letter-spacing:1.2px;text-transform:uppercase;color:var(--hare);
  font-weight:800}
.opens-row{display:grid;gap:12px;margin-top:12px}
@media(min-width:620px){.opens-row{grid-template-columns:repeat(3,1fr)}}
.open{display:flex;align-items:center;gap:12px;background:#fff;border-radius:12px;
  padding:12px 14px;border:2px solid var(--swan)}
.open b{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  font-size:15px;font-weight:900;color:#fff;flex:0 0 26px}
.open span{font-size:14px;font-weight:700;color:var(--eel-dark)}
.open.yes{border-color:#b6e88a}.open.yes b{background:var(--green)}
.open.some{border-color:#ffe08a}.open.some b{background:var(--bee);color:#4a3800}
.open.no{border-color:#ffc4c4}.open.no b{background:var(--cardinal)}
.opens-note{font-size:12px;color:var(--hare);margin:12px 0 0;font-weight:600}
.ladder-wrap{margin-top:var(--sp-32)}
.ladder-wrap svg{width:100%;height:auto}

/* ---------- 2. skills ---------- */
.skills{display:flex;flex-direction:column;gap:var(--sp-16)}
.sk{padding:14px 16px;border-radius:14px;border:2px solid var(--swan)}
.sk-strong{border-color:#b6e88a;background:#f6ffec}
.sk-weak{border-color:#ffd9a3;background:#fff9f0}
.sk-top{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.sk-name{font-size:17px;font-weight:900;color:var(--eel-dark)}
.sk-tag{font-size:10px;font-weight:900;letter-spacing:1px;text-transform:uppercase;
  padding:3px 9px;border-radius:99px}
.sk-tag.strong{background:var(--lime-pale);color:var(--green-deep)}
.sk-tag.weak{background:#ffe8cc;color:#95560a}
.sk-num{margin-left:auto;font-size:24px;font-weight:900;color:var(--eel-dark)}
.sk-track{display:block;height:12px;border-radius:99px;background:var(--swan);overflow:hidden}
.sk-track i{display:block;height:100%;width:var(--w);background:var(--c);border-radius:99px;
  transition:width .7s cubic-bezier(.3,.8,.3,1)}
.sk-plain{display:block;margin-top:7px;font-size:13px;color:var(--wolf);font-weight:600}

.verdict{margin-top:var(--sp-24);background:var(--blue-pale);border-radius:14px;
  padding:var(--sp-16) var(--sp-24)}
.verdict p{margin:0 0 8px;font-size:15px;color:#0f6e9c}
.verdict p:last-child{margin:0}
.verdict b{color:var(--blue-dark)}

.also{margin-top:var(--sp-24);border-top:1px solid var(--swan);padding-top:var(--sp-16)}
.also summary{cursor:pointer;font-size:14px;font-weight:800;color:var(--blue-dark)}
.combos{margin-top:var(--sp-16)}
.combo{display:grid;grid-template-columns:130px 42px 1fr;align-items:center;gap:12px;
  margin-bottom:9px}
.combo span{font-size:14px;font-weight:700;color:var(--wolf)}
.combo b{font-size:15px;font-weight:900;color:var(--eel-dark)}
.combo i{height:9px;border-radius:99px;background:var(--swan);position:relative}
.combo i::after{content:'';position:absolute;inset:0 auto 0 0;width:var(--w);
  background:var(--green);border-radius:99px}
.combos p{font-size:12px;color:var(--hare);margin:12px 0 0;font-weight:600}

/* ---------- 3. what to do ---------- */
.todos{display:flex;flex-direction:column;gap:var(--sp-16)}
.todo{display:flex;gap:var(--sp-16);border:2px solid var(--swan);border-bottom-width:4px;
  border-radius:16px;padding:var(--sp-24)}
.todo-n{flex:0 0 40px;width:40px;height:40px;border-radius:50%;color:#fff;font-weight:900;
  font-size:19px;display:grid;place-items:center}
.todo-body{min-width:0}
.todo-body h3{margin:6px 0 8px;font-size:18px}
.todo-lead{margin:0 0 12px;font-size:15px;color:var(--eel);font-weight:700}
.todo-also{margin:0 0 14px;padding-left:18px;color:var(--wolf);font-size:14px}
.todo-also li{margin-bottom:6px}

.target{display:flex;align-items:center;justify-content:center;gap:var(--sp-16);
  flex-wrap:wrap;margin-top:var(--sp-24);background:var(--lime-pale);border-radius:16px;
  padding:var(--sp-24);text-align:center}
.target span{font-size:13px;font-weight:800;color:#3f6d18;text-transform:uppercase;
  letter-spacing:.8px}
.target-move{display:flex;align-items:center;gap:14px}
.target-move b{font-size:38px;font-weight:900;color:var(--wolf);line-height:1}
.target-move b.up{color:var(--green-deep)}
.target-move i{font-size:26px;color:var(--green-deep);font-style:normal}

/* ---------- 4. responses ---------- */
.resp-grid{display:grid;gap:var(--sp-16)}
@media(min-width:840px){.resp-grid{grid-template-columns:1fr 1fr}}
.resp{border:2px solid var(--swan);border-bottom-width:4px;border-radius:16px;
  padding:var(--sp-24);display:flex;flex-direction:column}
.resp header{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:var(--sp-16)}
.resp-skill{font-size:10px;font-weight:900;letter-spacing:1px;text-transform:uppercase;
  color:#fff;background:var(--c);padding:4px 9px;border-radius:99px}
.resp header h3{margin:0;font-size:16px;width:100%}
.resp-avg{margin-left:auto;font-size:22px;font-weight:900;color:var(--eel-dark)}
.resp-avg small{font-size:12px;color:var(--hare)}
.resp-pips{margin-bottom:var(--sp-16)}
.pip-row{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.pip-row span{font-size:12px;font-weight:700;color:var(--wolf);width:88px;flex:0 0 88px}
.pips{display:flex;gap:4px}
.pips i{width:16px;height:9px;border-radius:3px;background:var(--swan)}
.pips i.on{background:var(--green)}
.resp-fluency{display:flex;gap:var(--sp-16);background:var(--snow);border-radius:12px;
  padding:12px;margin-bottom:var(--sp-16)}
.resp-fluency div{text-align:center;flex:1}
.resp-fluency b{display:block;font-size:18px;font-weight:900;color:var(--eel-dark)}
.resp-fluency span{font-size:11px;color:var(--hare);font-weight:700}
.resp-note{border-radius:12px;padding:12px 14px;margin-bottom:10px}
.resp-note span{display:block;font-size:10px;font-weight:900;letter-spacing:1px;
  text-transform:uppercase;margin-bottom:5px}
.resp-note p{margin:0;font-size:14px;line-height:1.55}
.resp-note.good{background:var(--lime-pale)}
.resp-note.good span{color:var(--green-deep)}
.resp-note.good p{color:#3f6d18}
.resp-note.fix{background:#fff4e5;margin-bottom:0}
.resp-note.fix span{color:#95560a}
.resp-note.fix p{color:#7a4a08}

/* ---------- 5. details ---------- */
.facts{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}
@media(min-width:620px){.facts{grid-template-columns:repeat(4,1fr)}}
.facts div{background:var(--snow);border-radius:14px;padding:16px;text-align:center}
.facts b{display:block;font-size:22px;font-weight:900;color:var(--eel-dark)}
.facts span{font-size:12px;color:var(--hare);font-weight:700}
.fine{font-size:12px;color:var(--hare);margin:var(--sp-16) 0 0;font-weight:600;line-height:1.7}

/* ---------- nav dropdowns ---------- */
.navitem{position:relative}
.navitem > .navlink{display:inline-flex;align-items:center;gap:5px}
.navitem > .navlink svg{transition:transform .15s}
.navitem:hover > .navlink svg,.navitem:focus-within > .navlink svg{transform:rotate(180deg)}
.navmenu{position:absolute;top:100%;left:50%;transform:translateX(-50%) translateY(6px);
  padding-top:12px;opacity:0;visibility:hidden;transition:opacity .14s,transform .14s;z-index:60}
.navitem:hover .navmenu,.navitem:focus-within .navmenu{opacity:1;visibility:visible;
  transform:translateX(-50%) translateY(0)}
.navmenu-in{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;
  border-radius:16px;padding:8px;min-width:250px;box-shadow:0 12px 28px rgba(0,0,0,.10)}
.navmenu-in a{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;
  font-size:14px;font-weight:800;color:var(--eel-dark);white-space:nowrap}
.navmenu-in a span{flex:1}
.navmenu-in a em{font-style:normal;font-size:11px;font-weight:800;letter-spacing:.6px;
  text-transform:uppercase;color:var(--hare)}
.navmenu-in a:hover{background:var(--lime-pale);color:var(--green-deep)}
.navmenu-in a:hover em{color:var(--green-deep)}
/* No special colour on the last item. It used to be blue-dark as a "see all"
   affordance, but that turns whatever happens to be last (a tool link now)
   into a jarring blue that reads as a selected state. Uniform items; hover is
   the only feedback. */
.navmenu-in a:last-child{border-top:1px solid var(--swan);margin-top:4px;padding-top:12px}
/* Mega menu — the "More" dropdown, categorised into 2 balanced columns. Anchored
   to its right edge (it is a right-side nav item) so a wide panel never overflows
   the viewport; groups render in CSS columns and never split (break-inside). */
.navmega{left:auto;right:0;transform:translateY(6px)}
.navitem:hover .navmega,.navitem:focus-within .navmega{transform:translateY(0)}
.navmega-in{columns:2;column-gap:6px;width:min(540px,92vw)}
/* Top spacing lives on the GROUP's padding, not the heading's margin: a top
   margin is truncated at a column break, so the right column (which starts at a
   break) lost its top space while the left kept it. Padding is preserved, so
   both columns now start level. */
.navmega-group{break-inside:avoid;padding:6px 0 8px}
.navmega-h{margin:0 12px 2px;font-size:10.5px;font-weight:900;letter-spacing:.09em;
  text-transform:uppercase;color:var(--hare)}
.navmega-in a{flex-direction:column;align-items:flex-start;gap:1px;padding:7px 12px;white-space:normal}
.navmega-in a span{flex:none}
.navmega-in a em{flex:none;font-size:10.5px;letter-spacing:.5px}
.navmega-in a:last-child{border-top:0;margin-top:0;padding-top:7px}
/* mobile drawer: sub-headings for the mega groups */
.dsubhead{margin:15px 0 3px;font-size:11px;font-weight:900;letter-spacing:.08em;
  text-transform:uppercase;color:var(--hare)}
.dsub .dsubhead:first-child{margin-top:3px}
@media(max-width:900px){.nav .navitem{display:none}}

/* ============================================================
   Page heroes.  INTERACTIVE_PAGE_RULES §4 and §10.

   Copy left, illustration right, on a tinted band from the fixed section
   palette. One wrap width, one alignment, held across every page.
   ============================================================ */
.hero-band{padding:var(--sp-64) 0 var(--sp-80)}
.hero-band.blue{background:var(--blue-pale)}
.hero-band.lime{background:var(--lime-pale)}
.hero-band.snow{background:var(--snow)}
.hero-band.white{background:#fff}

.hero-grid{display:grid;gap:var(--sp-32);align-items:center}
@media(min-width:900px){
  .hero-grid{grid-template-columns:1fr 1fr;gap:var(--sp-64)}
  .hero-grid.flip .hero-copy{order:2}
}
.hero-h1{font-size:clamp(30px,4.6vw,46px);font-weight:900;line-height:1.12;
  letter-spacing:-.02em;margin:0 0 var(--sp-16)}
.hero-h1.navy{color:var(--navy)}
.hero-h1.green{color:var(--green)}
.hero-h1.ink{color:var(--eel-dark)}
.hero-lede{font-size:17px;color:var(--wolf);margin:0 0 var(--sp-24);max-width:52ch}
.hero-list{list-style:none;margin:0 0 var(--sp-32);padding:0}
.hero-list li{display:flex;align-items:flex-start;gap:12px;margin-bottom:12px;
  font-size:15px;color:var(--eel);font-weight:700}
.hl-tick{flex:none;width:22px;height:22px;border-radius:50%;background:var(--green);
  color:#fff;display:grid;place-items:center;margin-top:1px}
.hero-art{display:flex;justify-content:center}
.hero-art svg{width:100%;max-width:480px;height:auto}
/* Named .hero-go, not .hero-cta — index.html already uses .hero-cta for the
   flex container that wraps its two buttons, and a shared stylesheet dropping
   a box-shadow on that container painted a green line across the page under
   "Practice by section". Component classes here must not reuse a name the
   hand-written page has already spent. */
.hero-go{box-shadow:0 4px 0 var(--green-dark)}
@media(max-width:899px){
  .hero-grid .hero-art{order:-1}
  .hero-band{padding:var(--sp-40) 0 var(--sp-48)}
}

/* ---------- §2 depth: soft shadow + hover lift ----------
   The 2px/4px bottom border stays — that is the Duolingo "physical button"
   language this whole site is built in, and §0 (consistency beats novelty)
   outranks the generic no-borders rule here. What was missing is the lift. */
.card,.stat,.widget,.todo,.resp,.table-wrap,.dd-col{transition:border-color .18s ease}
/* Hover is a border-colour change, matching the convention the hand-written
   landing page already used. An earlier pass replaced it with a translateY
   lift plus a drop shadow, which is a different design system bolted on. */
.card-link:hover,.stat:hover{border-color:var(--hare)}
/* Static cards are not interactive: no hover, no pointer. */
.card:not(.card-link){cursor:default}

/* ---------- icons inside chips and headings ---------- */
.card-ico{display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:14px;background:var(--lime-pale);
  color:var(--green-deep);margin-bottom:12px;font-size:22px}
.card-ico.blue{background:var(--blue-pale);color:var(--blue-dark)}
.card-ico.amber{background:#fff6d6;color:#a37400}
.card-ico.red{background:#ffecec;color:var(--cardinal)}
.callout-ico{display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;border-radius:10px;flex:none;font-size:17px}
.callout.green .callout-ico{background:#c6efa0;color:var(--green-deep)}
.callout.blue .callout-ico{background:#bfe7fb;color:var(--blue-dark)}
.callout.amber .callout-ico{background:#ffe9ad;color:#a37400}
.callout.red .callout-ico{background:#ffd4d4;color:var(--cardinal)}
.callout.violet .callout-ico{background:#e9d4fb;color:#8236c4}

/* ---------- alternating section tone ----------
   §10: pick a rhythm and hold it. Content sections alternate white / snow,
   with blue reserved for the one interactive block per page. */
.band.lime{background:var(--lime-pale)}
/* The report's h1 is the sidebar document label — sized as a label, not as a
   headline, but it is the page's single h1 (§12). */
h1.ds-label{font-size:11px;letter-spacing:1.4px;text-transform:uppercase;color:#b9b9b9;
  font-weight:800;margin:0;line-height:1.4}
/* Landing-hero proof bullets — centred, matching the generated pages' list. */
.hero-proof{list-style:none;margin:0 auto var(--sp-24);padding:0;max-width:520px;text-align:left}
.hero-proof li{display:flex;align-items:flex-start;gap:11px;margin-bottom:10px;
  font-size:15px;font-weight:700;color:var(--eel)}

/* ---------- comparison card ---------- */
.cmp{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;border-radius:18px;
  padding:var(--sp-16) var(--sp-24) var(--sp-24);max-width:520px;margin:0 auto var(--sp-32);
  text-align:left}
.cmp-head,.cmp-row{display:grid;grid-template-columns:1fr 74px 74px;align-items:center;gap:8px}
.cmp-head{padding-bottom:12px;border-bottom:2px solid var(--swan);margin-bottom:6px}
.cmp-head b{font-size:11px;font-weight:900;letter-spacing:.6px;text-transform:uppercase;
  text-align:center;line-height:1.25}
.cmp-mine{color:var(--green-deep)}
.cmp-theirs{color:var(--hare)}
.cmp-row{padding:11px 0;border-top:1px solid var(--snow)}
.cmp-row:first-of-type{border-top:0}
.cmp-label{font-size:14px;font-weight:700;color:var(--eel-dark)}
.cmp-y,.cmp-n{justify-self:center;display:grid;place-items:center;width:26px;height:26px;
  border-radius:50%}
.cmp-y{background:var(--green);color:#fff}
.cmp-n{background:var(--snow);position:relative}
.cmp-n::after{content:'';width:11px;height:3px;border-radius:2px;background:var(--hare)}
@media(max-width:560px){
  .cmp-head,.cmp-row{grid-template-columns:1fr 56px 56px}
  .cmp-label{font-size:13px}
}

/* ---------- CTA band illustration ---------- */
.cta-band{position:relative;overflow:hidden}
.cta-art svg{width:100%;height:auto;display:block}

/* ---------- landing hero: two columns ---------- */
.lp-hero-grid{display:grid;gap:var(--sp-32);align-items:center}
@media(min-width:940px){
  .lp-hero-grid{grid-template-columns:1.05fr .95fr;gap:var(--sp-64)}
  .lp-hero-copy{text-align:left}
  .lp-hero-copy .display,.lp-hero-copy .lede,
  .lp-hero-copy .hero-note,.lp-hero-copy .hero-disc{margin-left:0;margin-right:0;text-align:left}
  .lp-hero-copy .lede{max-width:none}
}

/* Two actions in a content-page hero. The task guides need both "drill this
   one task" and "sit a full test" reachable, and a single CTA slot forced a
   choice that belongs to the reader. */
.hero-btns{display:flex;flex-wrap:wrap;gap:var(--sp-12);align-items:center}
.hero-btns .hero-go{margin-top:0}
@media(max-width:520px){.hero-btns .btn{flex:1 1 100%}}
.lp-hero-btns{display:flex;flex-wrap:wrap;gap:var(--sp-12);margin:var(--sp-32) 0 0}
.lp-hero-btns .btn{flex:1 1 auto;min-width:190px}
.lp-hero-copy .hero-note{margin-top:var(--sp-16)}
.lp-hero-copy .hero-disc{margin-top:var(--sp-24)}
.lp-hero-art .cmp{margin:0;max-width:none}
@media(max-width:939px){
  /* Copy first, then the card. Hoisting the art above the headline pushed the
     actual message below the fold on a phone. */
  .lp-hero-art{order:0}
  .lp-hero-art .cmp{max-width:420px;margin-inline:auto}
  /* Both CTAs stay on one row; they shrink rather than stack. */
  .lp-hero-btns{flex-wrap:nowrap}
  .lp-hero-btns .btn{flex:1 1 0;min-width:0;padding-inline:12px;font-size:12.5px;
    white-space:nowrap}
}
/* The landing headline was sized for a full-width hero (up to 56px). In the
   two-column layout it only has half the row, so the old clamp overflowed
   into four lines and dominated the fold. */
/* The hero is the one section that should dominate the fold, so it gets a
   larger headline and generous room above and below before the green band
   starts. Sized against the half-width column it actually occupies. */
.lp-hero-copy .display{font-size:clamp(34px,4.2vw,54px);line-height:1.1;letter-spacing:-.022em}
.lp-hero-copy .lede{font-size:18px;margin-top:var(--sp-24)}
.lp-hero{padding-top:var(--sp-80);padding-bottom:var(--sp-96)}
@media(min-width:940px){
  .lp-hero{padding-top:var(--sp-96);padding-bottom:110px}
  .lp-hero-grid{gap:var(--sp-80)}
}
@media(max-width:939px){
  .lp-hero{padding-top:var(--sp-48);padding-bottom:var(--sp-64)}
  .lp-hero-copy .display{font-size:clamp(30px,7.4vw,40px)}
}

/* The press-down effect is suppressed on the header's primary CTA, where a
   big solid block dropping under a sticky bar reads as the whole nav moving.
   It is NOT suppressed on the ghost: this rule used to say `.site-head .btn`,
   which caught Sign In too and additionally forced a green shadow onto a white
   outlined button. The result was a secondary control that pressed differently
   from every other secondary control on the site. */
.site-head .btn-primary:active{transform:none;box-shadow:0 4px 0 var(--green-dark)}

/* ---------- subscore bars ----------
   subscoreBars() in ui.mjs has been emitting this markup since it was
   written and none of it was ever styled, so every use rendered as a plain
   text list — "Reading 115" with no bar. The ship gate now fails on an
   emitted-but-unstyled class so this cannot recur. */
.bars{margin:var(--sp-24) 0}
.bar-row{display:grid;grid-template-columns:104px 1fr 44px;align-items:center;
  gap:var(--sp-16);margin-bottom:12px}
.bar-label{font-size:14px;font-weight:800;color:var(--eel-dark)}
.bar-track{display:block;height:14px;border-radius:99px;background:var(--swan);overflow:hidden}
.bar-fill{display:block;height:100%;width:var(--w);background:var(--c);border-radius:99px;
  transition:width .7s cubic-bezier(.3,.8,.3,1)}
.bar-val{font-size:16px;font-weight:900;color:var(--eel-dark);text-align:right}
@media(max-width:520px){
  .bar-row{grid-template-columns:88px 1fr 38px;gap:12px}
  .bar-label{font-size:13px}
}

/* The typing caret drawn inside the task illustrations. */
.caret{animation:caretBlink 1.1s steps(1) infinite}
@keyframes caretBlink{0%,50%{opacity:1}51%,100%{opacity:0}}
@media(prefers-reduced-motion:reduce){.caret{animation:none}}

/* Wrapper inside a numbered step; the heading and copy carry the styling. */
.step-body{min-width:0}
/* The CTA illustration sits on the solid green band on the landing page, so
   its white accents read correctly there without a second variant. */
/* The landing page's full-bleed green band keeps its centred composition —
   it spans the viewport rather than sitting in a card — but the illustration
   was far too small for the space. */
.on-green-art{max-width:760px;margin:var(--sp-40) auto 0}
.on-green-art svg{width:100%;height:auto;display:block}

/* ---------- illustration size caps ----------
   The SVGs had no height bound, so on a tablet they grew to fill half a very
   wide column and swamped the copy beside them. */
.hero-art svg,.split-art svg,.rep-art svg{max-height:340px}
.cta-art svg{max-height:300px}
.on-green-art svg{max-height:360px}
@media(max-width:939px){
  .hero-art svg,.split-art svg,.cta-art svg,.rep-art svg,.on-green-art svg,
  .two-col .art svg{max-height:260px;max-width:420px;margin-inline:auto}
}
@media(max-width:560px){
  .hero-art svg,.split-art svg,.cta-art svg,.rep-art svg,.on-green-art svg,
  .two-col .art svg{max-height:200px}
}

/* ============================================================
   Content-page corrections.
   ============================================================ */

/* ---------- prose alignment ----------
   Paragraphs were capped at 78ch while tables and grids ran the full wrap, so
   a section's text started at one width and its table at another. Worse, a
   centred CTA inside a capped paragraph centred within the 78ch box rather
   than within the section, which is why the button looked randomly placed.
   Everything now shares one measure and one centre line. */
.prose{max-width:940px;margin-inline:auto}
.prose > p,.prose > ul,.prose > ol,.prose > h2,.prose > h3,
.prose > .callout,.prose > .pull{max-width:none}
.prose > p.cta-p,.prose > p[style*="text-align:center"]{text-align:center!important}

/* ---------- tables ----------
   The header row sat flush against the top edge of the card. */
.table-wrap th{padding:18px 16px 14px!important;vertical-align:bottom}
.table-wrap td{padding:15px 16px}
.table-wrap tr:last-child td{padding-bottom:18px}
table.data caption{padding:14px 16px 16px}

/* ---------- headings ----------
   Stops a single short word being orphaned onto its own line. */
h1,h2,h3,.hero-h1,.display,.sec-head h2{text-wrap:balance}

/* ---------- FAQ accordion ----------
   The open/close had no transition anywhere except the landing page, which
   had its own copy. This gives every generated page the same behaviour. */
details.faq .a{overflow:hidden}
details.faq[open] .a{animation:faqOpen .28s ease}
@keyframes faqOpen{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
details.faq summary::after{transition:transform .2s ease}
details.faq[open] summary::after{transform:rotate(180deg)}
@media(prefers-reduced-motion:reduce){
  details.faq[open] .a{animation:none}
  details.faq summary::after{transition:none}
}

/* ---------- footer gap ----------
   96px of footer margin on top of a section's own 64px bottom padding left a
   dead white band above the footer. The CTA band now closes every page, so
   the extra margin is not needed. */
.site-foot{margin-top:0}
main > section:last-of-type{padding-bottom:var(--sp-80)}
/* The closing band's wave sits directly above it with no seam. */
.wave-cta{display:block;width:100%;height:clamp(48px,6vw,92px);margin-bottom:-1px}

/* ---------- review wall (landing page) ----------
   No max-height clamp. It was inherited from the original multi-column
   layout, where a height cap was how you limited the wall; with a grid the
   extras being display:none already controls the height, and the clamp was
   only fighting the reveal. Height is now simply the natural height of
   whatever is visible.

   Grid, not columns: a multi-column container given more room spills into new
   columns sideways, which is what sent the expanded wall scrolling
   horizontally. */
.wall{display:grid!important;grid-template-columns:repeat(3,1fr);gap:var(--sp-24);
  align-items:start;max-height:none!important;overflow:visible!important}
.wall .extra{display:none}
.wall.open .extra{display:block}
.wall .t{margin:0}
@media(max-width:900px){.wall{grid-template-columns:repeat(2,1fr)}}
@media(max-width:620px){.wall{grid-template-columns:1fr}}

/* Section headings were set at the body line-height, which is loose for
   two-line display type and left the lines drifting apart. */
.sec-head h2,.prose > h2,h2{line-height:1.18}
.sec-head h2{margin-bottom:var(--sp-12)}

/* Two adjacent tinted bands showed a hairline of page background between
   them. Collapsing the seam means a run of same-tone sections reads as one
   surface, which is what it looks like it should be. */
.band.snow + .band.snow,.band.blue + .band.blue,.band.lime + .band.lime{padding-top:0}

/* ============================================================
   Closing CTA — full-bleed green band.

   Pairs with a grey FAQ above it, matching the landing page. The boxed
   variant stacked a section's 64px padding on top of the card's own 80px
   margin, leaving ~144px of dead white above it; a full-bleed band butts
   straight against the section above, so there is no seam to get wrong.
   ============================================================ */
.cta-full{background:var(--green);padding:var(--sp-80) 0 var(--sp-64);text-align:center;
  margin:0}
.cta-full .wrap{display:grid;justify-items:center;gap:var(--sp-16)}
.cta-full h2{color:#fff;margin:0;font-size:clamp(26px,3.6vw,38px);line-height:1.14;
  max-width:18ch}
.cta-full p{color:#e8ffd4;margin:0;font-size:17px;max-width:46ch}
.cta-full .btn{margin-top:var(--sp-12)}
.cta-full .cta-art{max-width:600px;margin:var(--sp-24) auto 0;width:100%}
.cta-full .cta-art svg{width:100%;height:auto;max-height:300px}
@media(max-width:700px){
  .cta-full{padding:var(--sp-48) 0 var(--sp-40)}
  .cta-full .cta-art{max-width:420px}
}

/* A page's last content section sits directly against the band. */
main > section.band + .cta-full,
main > section + .cta-full{margin-top:0}
main > section:last-of-type{padding-bottom:var(--sp-64)}
/* .btn-white existed only in index.html's inline stylesheet; the generated
   pages now use it on the green CTA band, so it belongs here. Same physical
   depth as the other weights. */
.btn-white{background:#fff;color:var(--green-deep);
  border:2px solid #fff;box-shadow:0 4px 0 #3f8c00}
.btn-white:hover{filter:brightness(.97)}
.btn-white:active{transform:translateY(3px);box-shadow:0 1px 0 #3f8c00}

/* Pages that author their own closing CTA inline (task pages, the report)
   keep the boxed card. It pairs with a white section, so it needs no extra
   top margin fighting the section padding above it. */
.cta-band.cta-inline{margin-top:var(--sp-48)}
/* The review wall and its wrapper are layout containers, not cards. Only the
   individual .t testimonials carry a border. Declared explicitly because the
   expanded wall was rendering with two nested outlines and I could not find
   the rule producing them in either stylesheet — this states the intent so
   the boxes cannot come back from a selector I missed. */
.wall,.wall-wrap{border:0;background:none;box-shadow:none;padding:0}

/* ---------- brand lockup ----------
   Mark on the left, wordmark on the right. "DET" carries the navy from the
   artwork and the rest stays green, matching the two weights in the original
   wordmark without shipping the raster. */
.logo{display:inline-flex;align-items:center;gap:10px;text-decoration:none}
.brand-mark{flex:none}
.logo .brand-text,.logo{font-weight:900;font-size:19px;line-height:1;color:#58cc02}
.logo b{color:#13253f;font-weight:900}
.site-foot .logo{font-size:17px}
@media(max-width:560px){.logo{font-size:16px}.brand-mark{width:28px!important;height:28px!important}}

/* Task tile. Authored on the landing page first; promoted here so the Tasks
   and section pages draw the identical square instead of a bare card. The
   background colour is per-task and arrives inline from site/taskicons.mjs. */
.qicon{width:64px;height:64px;border-radius:18px;display:flex;align-items:center;
  justify-content:center;margin-bottom:var(--sp-16);flex:none}
.qicon svg{width:32px;height:32px}
.card .qicon{width:56px;height:56px;border-radius:16px;margin-bottom:var(--sp-12)}

/* Interactive Listening, stage 1: guided sentence completion. The stem is
   plain text and only the blank is an input, matching the real task where
   the grammar is given to you and the blank carries the content. */
.scen{text-align:center;color:var(--wolf);font-size:15px;margin:0 0 var(--sp-20)}
.openers{display:flex;flex-direction:column;gap:var(--sp-16);max-width:620px;margin:0 auto}
.opener{margin:0}
.opener-q{font-weight:700;font-size:15px;margin-bottom:6px}
.opener-a{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap;
  background:var(--snow);border-radius:var(--r-12);padding:12px 14px}
.opener-in{flex:1 1 160px;min-width:120px;border:0;border-bottom:2px solid var(--blue);
  background:transparent;font:inherit;font-size:15px;padding:2px 4px;outline:none}
.opener-in:focus{border-bottom-color:var(--green)}

/* ---------- mobile navigation ----------
   The navlinks are display:none below 1080px. That was the whole of the
   responsive story, which meant a phone visitor could reach Sign in and Take
   a test and nothing else — no mock tests, no section practice, no scoring
   guide. The button below is what makes that hiding legitimate. */
.navburger{display:none;align-items:center;justify-content:center;width:40px;height:40px;
  border:2px solid var(--swan);border-bottom-width:4px;border-radius:12px;background:#fff;
  color:var(--eel);cursor:pointer;padding:0;flex:none}
.navburger:hover{background:var(--snow);border-color:var(--hare)}
.navburger:active{transform:translateY(3px);box-shadow:0 1px 0 var(--swan)}
.navburger[aria-expanded=true]{border-color:var(--green);color:var(--green-deep)}
@media(max-width:1080px){.navburger{display:inline-flex}}

/* Full-viewport overlay below the header. `top` is the header height (set
   precisely in JS; the value here is a fallback), and fixed + bottom:0 means
   the drawer covers everything under the bar — no page content bleeds through
   below a short menu, which is what "the hamburger must fully hide" needs. */
.navdrawer{position:fixed;left:0;right:0;bottom:0;top:62px;z-index:70;background:#fff;
  box-shadow:0 16px 30px rgba(0,0,0,.10);
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.navdrawer[hidden]{display:none}
.navdrawer-in{padding:6px 20px 48px;max-width:var(--wrap,1180px);margin:0 auto}
/* A separator between each top-level row (accordion group or solo link). */
.navdrawer-in > * + *{border-top:1px solid var(--snow)}
.navdrawer .dhead{display:block;padding:16px 4px;font-size:16px;font-weight:900;
  color:var(--eel-dark)}
/* Solo rows (Question types, Blog, My progress, Sign in) navigate directly
   rather than expanding, so they carry no chevron. */
.navdrawer .dhead-solo{color:var(--eel-dark)}
/* Groups are native <details> accordions, collapsed by default. The summary
   is the tappable header with a chevron that flips when open. */
.navdrawer .dgroup{padding:0}
.navdrawer summary.dhead{display:flex;align-items:center;justify-content:space-between;
  cursor:pointer;list-style:none;user-select:none;-webkit-tap-highlight-color:transparent}
.navdrawer summary.dhead::-webkit-details-marker{display:none}
.navdrawer summary.dhead::marker{content:""}
.navdrawer .dchev{flex:none;color:var(--hare);transition:transform .2s ease}
.navdrawer details[open] > summary .dchev{transform:rotate(180deg)}
.navdrawer .dsub{padding-bottom:10px}
.navdrawer .dlink{display:block;padding:11px 4px 11px 18px;font-size:14.5px;font-weight:700;
  color:var(--wolf)}
.navdrawer .dlink:hover,.navdrawer .dlink:active,.navdrawer .dhead:hover{color:var(--green-deep)}
/* .site-head is already position:sticky (see the top of this file), which is
   the positioning context the drawer needs. Nothing to add here. */

/* ============================================================
   Blog — guides on top, then a searchable, categorised post list.
   The post cards are their own component (not .card) so the blog can carry a
   cover image and its own hover feel without disturbing the guide grid.
   ============================================================ */

/* Toolbar: search box on the left, category chips on the right. */
.blog-toolbar{display:flex;flex-wrap:wrap;gap:var(--sp-16);align-items:center;
  justify-content:space-between;margin:0 0 var(--sp-24)}
.blog-search-wrap{position:relative;display:flex;align-items:center;flex:1 1 260px;max-width:440px}
.blog-search-ico{position:absolute;left:16px;width:18px;height:18px;color:var(--hare);pointer-events:none}
.blog-search{width:100%;font:inherit;font-weight:700;font-size:15px;color:var(--eel-dark);
  background:#fff;border:2px solid var(--swan);border-radius:999px;
  padding:12px 18px 12px 44px;outline:none;transition:border-color .18s ease}
.blog-search::placeholder{color:var(--hare);font-weight:600}
.blog-search:focus{border-color:var(--blue)}
.blog-chips{display:flex;flex-wrap:wrap;gap:8px}
.blog-chip{font:inherit;font-weight:800;font-size:13px;letter-spacing:.2px;color:var(--wolf);
  background:#fff;border:2px solid var(--swan);border-radius:999px;padding:9px 16px;cursor:pointer;
  transition:border-color .15s ease,color .15s ease,background .15s ease;white-space:nowrap}
.blog-chip:hover{border-color:var(--hare);color:var(--eel-dark)}
.blog-chip[aria-pressed="true"]{background:var(--eel-dark);border-color:var(--eel-dark);color:#fff}

/* The post grid. */
.blog-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-24);margin-top:var(--sp-24)}
@media(min-width:640px){.blog-grid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:980px){.blog-grid{grid-template-columns:repeat(3,1fr)}}

.blog-card{display:flex;flex-direction:column;background:#fff;border:2px solid var(--swan);
  border-bottom-width:4px;border-radius:var(--r-card);overflow:hidden;color:inherit;
  transition:border-color .18s ease,transform .18s ease}
.blog-card:hover{border-color:var(--hare);transform:translateY(-3px)}
.blog-card-art{display:flex;align-items:center;justify-content:center;height:132px;flex:none;
  color:var(--blue-dark);background:var(--blue-pale);transition:transform .25s ease}
.blog-card:hover .blog-card-art{transform:scale(1.06)}
.blog-card-body{display:flex;flex-direction:column;gap:10px;padding:var(--sp-20) var(--sp-20) var(--sp-24)}
.blog-card-body h3{font-size:19px;font-weight:800;line-height:1.25;color:var(--eel-dark);margin:0}
.blog-card-body p{color:var(--wolf);font-size:14.5px;line-height:1.55;margin:0}
.blog-card .blog-meta{margin-top:auto}

/* Featured: the newest post, given the wide two-column treatment. */
.blog-feat{margin-bottom:var(--sp-24)}
@media(min-width:760px){
  .blog-feat{display:grid;grid-template-columns:minmax(0,42%) 1fr;align-items:stretch}
  .blog-feat .blog-card-art{height:100%;min-height:220px}
  .blog-feat .blog-card-body{justify-content:center;gap:12px;padding:var(--sp-32) var(--sp-40)}
  .blog-feat .blog-card-body h3{font-size:26px}
  .blog-feat .blog-card-body p{font-size:16px}
}

/* Category tints drive both the card cover and its little pill. */
.blog-card-art.c-blue{background:var(--blue-pale);color:var(--blue-dark)}
.blog-card-art.c-green{background:var(--lime-pale);color:var(--green-deep)}
.blog-card-art.c-violet{background:#f3e8ff;color:#8236c4}

.blog-cat{align-self:flex-start;display:inline-block;font-size:11.5px;font-weight:800;
  letter-spacing:.6px;text-transform:uppercase;padding:4px 10px;border-radius:999px;
  background:var(--snow);color:var(--wolf)}
.blog-cat.c-blue{background:var(--blue-pale);color:var(--blue-dark)}
.blog-cat.c-green{background:var(--lime-pale);color:var(--green-deep)}
.blog-cat.c-violet{background:#f3e8ff;color:#8236c4}

.blog-meta{font-size:13px;font-weight:700;color:var(--hare)}
.blog-empty{margin-top:var(--sp-24);text-align:center;color:var(--wolf);font-weight:700}

/* The post reading page — a narrow column, distinct from the wider guides. */
.post-wrap{max-width:760px;margin:0 auto}
.post-meta{display:flex;flex-wrap:wrap;align-items:center;gap:14px;margin:0 0 var(--sp-24);
  padding-bottom:var(--sp-20);border-bottom:1px solid var(--swan)}
.post-meta .blog-cat{text-decoration:none}
.post-body > h2:first-of-type{margin-top:var(--sp-32)}

/* Post cover illustrations — on the card, and enlarged in the post hero. */
.blog-cover{display:block}
.blog-card-art .blog-cover{height:80%;width:auto;max-width:88%}
.blog-feat .blog-card-art .blog-cover{height:72%}

/* The blog post hero: narrow, centred, one column. Title + preheader +
   illustration + deck + one CTA — no proof bullets, no question-type grid. */
.post-hero{padding:var(--sp-48) 0 var(--sp-40)}
.post-hero-in{max-width:660px;margin:0 auto;display:flex;flex-direction:column;
  align-items:center;text-align:center;gap:var(--sp-16)}
.post-hero-in .kicker{margin:0}
.post-hero-art{width:min(300px,74%)}
.post-hero-art .blog-cover{width:100%;height:auto}
.post-hero-in .hero-h1{margin:0}
.post-hero-in .hero-lede{margin:0;max-width:60ch}
.post-hero-in .hero-btns{margin-top:var(--sp-8);justify-content:center}

/* ---------- Fill in the Blanks free tool ----------
   Mirrors the .cd-* demo styling, but this is a full looping drill with its
   own header (streak/score) and feedback line. */
.hero-tool{width:100%;max-width:560px}
.fibtool .fib-head{display:flex;justify-content:space-between;align-items:center;
  gap:12px;margin-bottom:14px;font-size:13px;font-weight:800;color:var(--hare)}
.fibtool .fib-score b,.fibtool .fib-progress b{color:var(--eel-dark)}
.fibtool .fib-instr{font-size:13px;color:var(--wolf);font-weight:700;margin:0 0 12px}
.fibtool .fib-sentence{font-size:19px;line-height:2.1;color:var(--eel-dark);
  font-weight:600;margin:0 0 var(--sp-16);min-height:2.4em}
.fib-word{white-space:nowrap}
.fib-seen{border-bottom:2px solid var(--swan)}
.fib-in{font:inherit;font-size:18px;font-weight:800;color:var(--blue-dark);border:0;
  border-bottom:2.5px solid var(--blue);background:var(--blue-pale);border-radius:4px 4px 0 0;
  padding:0 3px;min-width:2ch;outline:none;text-align:center;
  line-height:1.4;height:1.5em;vertical-align:baseline;box-sizing:content-box}
.fib-in:focus{background:#c9ecfd}
.fib-in.right{color:var(--green-deep);border-bottom-color:var(--green);background:var(--lime-pale)}
.fib-in.wrong{color:var(--cardinal);border-bottom-color:var(--cardinal);background:#ffecec}
.fib-actions{display:flex;gap:12px;flex-wrap:wrap}
.fib-actions .btn-ghost.fib-skip{margin-left:auto}
.fib-feedback{margin:14px 0 0;font-size:14px;font-weight:800;min-height:1.3em}
.fib-feedback.ok{color:var(--green-deep)}
.fib-feedback.no{color:var(--cardinal)}
/* Helper spans/buttons in the tool that the gate wants explicitly declared.
   They inherit their real styling from .btn and .fib-head; these rules just
   register the class so the drift gate sees them. */
.fib-check,.fib-next{min-width:0}
.fib-skip{background:none}
.fib-progress,.fib-streak,.fib-correct,.fib-done,.fib-n{font-variant-numeric:tabular-nums}
/* Real or Fake Word tool — reuses .fib-head/.fib-score/.fib-feedback. */
.wordtool .wt-instr{font-size:14px;color:var(--wolf);font-weight:800;margin:0 0 10px}
.wordtool .wt-word{font-size:38px;font-weight:900;color:var(--eel-dark);letter-spacing:-.01em;
  text-align:center;margin:8px 0 20px;padding:18px;background:var(--snow);border-radius:14px;
  min-height:1.2em;transition:background .15s,color .15s}
.wordtool .wt-word.right{background:var(--lime-pale);color:var(--green-deep)}
.wordtool .wt-word.wrong{background:#ffecec;color:var(--cardinal)}
.wt-actions{display:flex;gap:12px;flex-wrap:wrap}
.wt-actions .btn{flex:1;min-width:120px}
.wt-instr,.wt-word,.wt-yes,.wt-no,.wt-feedback,.wt-n,.wt-streak,.wt-correct,.wt-done{font-variant-numeric:tabular-nums}

/* ---------- nav CTA group + signed-in avatar ----------
   Sign in and Take a test used to be two independent nav children, so the
   nav's 24px gap sat between them and they read as far apart. Grouping them
   with their own tight gap fixes the spacing; the group is also where the
   avatar takes the place of Sign in once a session is detected. */
.nav-cta{display:inline-flex;align-items:center;gap:var(--sp-8)}
.nav-signin{white-space:nowrap}
.nav-avatar{display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;border-radius:50%;background:var(--green);color:#fff;
  font-weight:900;font-size:15px;text-decoration:none;flex:none;
  box-shadow:0 3px 0 var(--green-deep);text-transform:uppercase}
.nav-avatar:hover{filter:brightness(1.05)}
.nav-avatar:active{transform:translateY(2px);box-shadow:0 1px 0 var(--green-deep)}

/* Score validity checker tool. */
.validtool{position:relative}
.validtool .vt-label{display:block;font-size:14px;font-weight:800;color:var(--wolf);margin-bottom:10px}
/* A custom trigger + calendar, never the native date input — the browser's own
   picker ignores the palette and looks like a different product. */
.validtool .vt-trigger{width:100%;display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:13px 16px;border:2px solid var(--swan);border-bottom-width:4px;border-radius:14px;background:#fff;
  font:inherit;font-size:16px;font-weight:800;color:var(--eel-dark);cursor:pointer;text-align:left}
.validtool .vt-trigger:hover{background:var(--snow)}
.validtool .vt-trigger[aria-expanded=true]{border-color:var(--blue)}
.validtool .vt-trigger svg{width:20px;height:20px;max-width:20px;flex:none;margin:0}
.validtool .vt-trigger-txt.vt-empty{color:var(--hare);font-weight:700}
.vt-cal{margin-top:10px;border:2px solid var(--swan);border-radius:16px;padding:12px;background:#fff}
.vt-cal[hidden]{display:none}
.vt-cal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.vt-cal-head b{font-size:14px;font-weight:900;color:var(--eel-dark)}
.vt-nav{width:30px;height:30px;border:2px solid var(--swan);border-radius:9px;background:#fff;
  cursor:pointer;font:inherit;font-weight:900;color:var(--wolf);line-height:1}
.vt-nav:hover:not([disabled]){border-color:var(--blue);color:var(--blue)}
.vt-nav[disabled]{opacity:.3;cursor:not-allowed}
.vt-dow{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}
.vt-dow span{text-align:center;font-size:10px;font-weight:900;color:var(--hare);letter-spacing:.04em}
.vt-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.vt-day{aspect-ratio:1;border:0;border-radius:9px;background:none;font:inherit;font-size:13px;
  font-weight:800;color:var(--eel-dark);cursor:pointer}
.vt-day:hover:not([disabled]):not(.vt-on){background:var(--blue-pale)}
.vt-day[disabled]{color:var(--swan);cursor:default}
.vt-day.out{color:#e8e8e8}
.vt-day.vt-today{box-shadow:inset 0 0 0 2px var(--swan)}
.vt-day.vt-on{background:var(--blue);color:#fff;box-shadow:0 2px 0 var(--blue-dark)}
.vt-result{margin-top:18px;padding:18px;border-radius:14px;border:2px solid var(--swan)}
.vt-result[hidden]{display:none}
.vt-result.valid{background:var(--lime-pale);border-color:var(--green)}
.vt-result.expired{background:#ffecec;border-color:var(--cardinal)}
.vt-badge{display:inline-block;font-size:12px;font-weight:900;letter-spacing:.04em;text-transform:uppercase;
  padding:5px 12px;border-radius:99px;margin-bottom:10px}
.vt-result.valid .vt-badge{background:var(--green);color:#fff}
.vt-result.expired .vt-badge{background:var(--cardinal);color:#fff}
.vt-line{margin:0 0 6px;font-size:17px;font-weight:800;color:var(--eel-dark)}
.vt-sub{margin:0;font-size:14px;color:var(--wolf);font-weight:600}
.validtool .vt-hint{margin:14px 0 0;font-size:13px;color:var(--hare);font-weight:600}
.vt-label,.vt-date,.vt-badge,.vt-line,.vt-sub,.vt-hint{font-variant-numeric:tabular-nums}

/* ---------- contact form ---------- */
.contact-formwrap{width:100%;max-width:480px}
.contact-form{background:#fff;border:2px solid var(--swan);border-bottom-width:4px;
  border-radius:20px;padding:24px}
.cf-field{margin-bottom:16px}
.cf-field label{display:block;font-size:11px;font-weight:900;letter-spacing:.08em;
  text-transform:uppercase;color:var(--hare);margin-bottom:7px}
.cf-field input,.cf-field textarea{width:100%;font:inherit;font-size:15px;font-weight:600;
  color:var(--eel-dark);padding:12px 14px;border:2px solid var(--swan);border-radius:12px;
  background:var(--snow);resize:vertical}
.cf-field input:focus,.cf-field textarea:focus{outline:none;border-color:var(--blue);background:#fff}
.cf-hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.cf-submit{margin-top:4px}
.cf-status{margin:12px 0 0;font-size:13px;font-weight:700;min-height:1.2em}
.cf-status.ok{color:var(--green-deep)}
.cf-status.err{color:var(--cardinal)}

/* ---------- English level (CEFR) test tool ---------- */
.leveltool .lv-intro{font-size:14px;line-height:1.55;color:var(--wolf);font-weight:600;margin:0 0 16px}
.leveltool .lv-fineprint{margin:10px 0 0;font-size:12px;color:var(--hare);font-weight:600;text-align:center}
.lv-head{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.lv-progress{font-size:13px;font-weight:800;color:var(--hare);white-space:nowrap}
.lv-progress b{color:var(--eel-dark)}
.lv-bar{flex:1;height:8px;border-radius:99px;background:var(--swan);overflow:hidden}
.lv-bar i{display:block;height:100%;border-radius:99px;background:var(--green);transition:width .3s ease}
.lv-q{font-size:14px;font-weight:800;color:var(--wolf);margin:0 0 10px}
.lv-word{font-size:34px;font-weight:900;color:var(--eel-dark);text-align:center;margin:6px 0 18px;
  padding:16px;background:var(--snow);border-radius:14px}
.lv-sentence{font-size:18px;line-height:2;color:var(--eel-dark);font-weight:600;margin:0 0 16px}
.lv-seen{border-bottom:2px solid var(--swan)}
.lv-in{font:inherit;font-size:17px;font-weight:800;color:var(--blue-dark);border:0;
  border-bottom:2.5px solid var(--blue);background:var(--blue-pale);border-radius:4px 4px 0 0;
  padding:0 3px;text-align:center;line-height:1.4;height:1.5em;vertical-align:baseline;box-sizing:content-box}
.lv-in:focus{background:#c9ecfd;outline:none}
.lv-actions{display:flex;gap:12px;flex-wrap:wrap}
.lv-actions .btn{flex:1;min-width:130px}
.lv-result{text-align:center}
.lv-badge{font-size:12px;font-weight:900;letter-spacing:.06em;text-transform:uppercase;color:var(--hare)}
.lv-cefr{font-size:56px;font-weight:900;color:var(--green-deep);line-height:1.05;margin:4px 0}
.lv-cefr-name{font-size:16px;font-weight:800;color:var(--eel-dark);margin:0 0 12px}
.lv-est{font-size:15px;color:var(--eel-dark);font-weight:600;margin:0 0 10px}
.lv-est b{color:var(--green-deep)}
.lv-note{font-size:13px;color:var(--wolf);font-weight:600;line-height:1.5;margin:0 0 18px}
.lv-cta{display:flex;flex-direction:column;gap:10px}
/* Register these classes for the drift gate WITHOUT overriding [hidden] —
   an explicit display:block would beat the hidden attribute and show all
   three panels at once. */
.lv-item{min-height:1em}
.lv-start{text-align:left}
.lv-quiz{text-align:left}
.lv-gapwrap{display:inline}
.lv-begin,.lv-again{cursor:pointer}
.leveltool [hidden]{display:none !important}
.lv-q,.lv-word,.lv-cefr,.lv-est,.lv-progress{font-variant-numeric:tabular-nums}

/* ---------- one-word-substitution page: jump nav + self-test quiz ---------- */
.ows-toc{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:10px 0 34px}
.ows-toc b{font-size:13px;font-weight:900;color:var(--eel-dark);margin-right:2px}
.ows-toc a{display:inline-block;padding:5px 11px;border:2px solid var(--swan);border-radius:999px;
  color:var(--wolf);font-size:13px;font-weight:700;text-decoration:none;background:#fff}
.ows-toc a:hover{border-color:var(--blue);color:var(--blue-dark)}
.ows-toc a.oq-jump{border-color:var(--green);color:var(--green-deep)}
.ows-cat{scroll-margin-top:84px}
.owsquiz{border:2px solid var(--swan);border-bottom-width:4px;border-radius:18px;padding:22px;
  background:#fff;max-width:640px;margin:0 auto}
.oq-head{display:flex;justify-content:space-between;align-items:center;gap:10px;
  font-size:12px;font-weight:900;letter-spacing:.04em;text-transform:uppercase;color:var(--hare);margin-bottom:14px}
.oq-count,.oq-score{font-variant-numeric:tabular-nums}
.oq-meaning{font-size:20px;font-weight:600;color:var(--eel-dark);line-height:1.4;margin:0 0 20px;
  min-height:52px;text-align:center}
.oq-meaning strong{font-weight:800;color:var(--blue-dark);background:var(--blue-pale);
  padding:1px 9px;border-radius:7px}
.oq-opts{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media(max-width:520px){.oq-opts{grid-template-columns:1fr}}
.oq-opt{padding:13px 14px;border:2px solid var(--swan);border-bottom-width:4px;border-radius:13px;background:#fff;
  font:inherit;font-size:16px;font-weight:800;color:var(--eel-dark);cursor:pointer;text-align:left;transition:none}
.oq-opt:hover{border-color:var(--blue);background:var(--blue-pale)}
.oq-opt.ok{border-color:var(--green);background:var(--lime-pale);color:var(--green-deep)}
.oq-opt.bad{border-color:var(--cardinal);background:#ffecec;color:var(--cardinal)}
.oq-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:15px;min-height:40px}
.oq-msg{font-size:14px;font-weight:800}
.oq-msg.ok{color:var(--green-deep)}
.oq-msg.bad{color:var(--cardinal)}
.oq-next{flex:none}

/* ---------- parts-of-speech page: the eight cards ---------- */
.pos-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin:6px 0}
@media(max-width:640px){.pos-grid{grid-template-columns:1fr}}
.pos-item{border:2px solid var(--swan);border-bottom-width:4px;border-radius:14px;padding:16px 18px;
  background:#fff;scroll-margin-top:84px}
.pos-item h3{margin:0 0 6px;font-size:17px;color:var(--eel-dark)}
.pos-def{margin:0 0 9px;color:var(--wolf);font-size:15px}
.pos-ex,.pos-sent{margin:0 0 5px;font-size:14px;color:var(--eel-dark)}
.pos-ex strong,.pos-sent strong{color:var(--blue-dark)}
.pos-sent{margin-bottom:0}

/* /learn/vocabulary — live search + word tables (Day 4) */
.vocabsearch{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin:8px 0 10px}
.vocabsearch input{flex:1 1 320px;min-width:0;font:inherit;font-size:16px;padding:12px 16px;
  border:2px solid var(--swan);border-bottom-width:3px;border-radius:14px;background:var(--white);color:var(--eel-dark)}
.vocabsearch input::placeholder{color:var(--hare)}
.vocabsearch input:focus{outline:none;border-color:var(--blue)}
.vs-count{font-size:13px;font-weight:800;color:var(--hare);white-space:nowrap}
.vocab-cat{scroll-margin-top:80px}
.vpos{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;
  color:var(--blue-dark);background:var(--blue-pale);padding:1px 7px;border-radius:6px;
  margin-left:7px;vertical-align:middle;white-space:nowrap}
/* /learn/english-tenses — the 12-tense chart */
.tenchart{margin:0}
.ten-form{font-size:12.5px;font-weight:700;color:var(--wolf);white-space:nowrap}

/* /tools/grammar-test — the interactive grammar test widget */
.grammartest{border:2px solid var(--swan);border-bottom-width:4px;border-radius:18px;padding:22px;max-width:640px;margin:6px auto 0}
/* Scope [hidden] inside the widget so the .btn display rule can't beat the bare
   hidden attribute and show the empty "next" button (same fix as .leveltool). */
.grammartest [hidden]{display:none !important}
.gt-head{display:flex;justify-content:space-between;font-size:13px;font-weight:800;color:var(--hare);font-variant-numeric:tabular-nums}
.gt-bar{height:8px;background:var(--snow);border-radius:5px;overflow:hidden;margin:8px 0 20px}
.gt-bar i{display:block;height:100%;width:0;background:var(--green);border-radius:5px;transition:width .3s}
.gt-q{font-size:19px;font-weight:700;color:var(--eel-dark);line-height:1.45;margin:0 0 18px}
.gt-opts{display:grid;gap:10px}
.gt-opt{text-align:left;font:inherit;font-size:16px;font-weight:700;color:var(--eel-dark);background:var(--white);
  border:2px solid var(--swan);border-radius:12px;padding:12px 16px;cursor:pointer;transition:border-color .12s,background .12s}
.gt-opt:hover:not(:disabled){border-color:var(--blue)}
.gt-opt:disabled{cursor:default}
.gt-opt.ok{border-color:var(--green);background:var(--lime-pale);color:var(--green-deep)}
.gt-opt.bad{border-color:var(--cardinal);background:#fff2f2;color:var(--cardinal)}
.gt-msg{margin:16px 0 0;font-size:14px;color:var(--wolf);line-height:1.55}
.gt-msg .ok{color:var(--green-deep)} .gt-msg .bad{color:var(--cardinal)}
.gt-foot{margin-top:16px}
.gt-result{text-align:center;padding:10px 0}
.gt-big{font-size:46px;font-weight:900;color:var(--eel-dark);margin:0;letter-spacing:-.02em}
.gt-pct{font-size:16px;font-weight:700;color:var(--wolf);margin:4px 0 14px}
.gt-rec{font-size:15px;font-weight:700;color:var(--eel-dark);margin:0 0 12px}
.gt-note{font-size:13px;color:var(--hare);max-width:460px;margin:0 auto 18px;line-height:1.5}
