/* BCINprep stylesheet, rebuilt against the conversion audit.
   Fixes: 6-token type scale (was 18 sizes, 11 inside a 1.53x range), weight hierarchy,
   accent reserved for one action per viewport, real elevation, three section-gap tiers,
   AA contrast, focus-visible, measure caps. */

:root{
  /* ink: three tiers, all AA or better on paper */
  --ink:#15201b;        /* 16.7:1 */
  --ink2:#45524b;       /* 8.2:1  */
  --ink3:#5f6b65;       /* 5.4:1, was #6d7a73 at 4.49 which failed AA */
  --paper:#ffffff;
  --wash:#eef2f0;       /* deepened from #f4f6f5 which was a 3.3 L* step, invisible */
  --wash2:#e4eae7;
  /* structure vs action: navy carries structure, green carries ONLY the buy action */
  --navy:#16324f;
  --navy-dk:#0d2137;   /* pressed/hover for a filled navy control, the way --accent-dk serves green */
  --navy-wash:#e8eef4;
  /* THE THIRD ROLE: add to cart. Navy was not enough to catch the eye and green cannot be borrowed,
     so the add controls get their own hue. Amber for "put it in the cart", green for "pay" is the
     most learned split in online retail, so it costs a reader nothing to understand. It also keeps
     the rule below intact: the only green button on the page is still the one that takes money. */
  --add:#b8480f;
  --add-dk:#93380b;
  --add-wash:#fdf0e9;
  --accent:#0b6e4f;
  --accent-dk:#075c41;
  --accent-wash:#e3f0ea;
  --warn:#8a5a00;
  --warn-wash:#fdf5e6;
  --danger:#a33427;
  --danger-wash:#faeae7;
  --rule:#cfd8d4;       /* deepened from #dde3e0 (1.19:1). Decorative separators only. */
  --rule-strong:#b6c2bc;
  /* WCAG 1.4.11 wants 3:1 for any boundary that IS the control, so interactive borders (quiz
     options, the navigator grid, form inputs) use this instead of --rule: 3.46:1 on paper,
     3.07:1 on wash. --rule at 1.46:1 is fine for a table rule and not fine for a button. */
  --rule-ui:#7f8d87;

  /* type: 7 tokens on a ~1.33 scale. Every level is a real level. */
  --fs-micro:0.8125rem;                        /* 13px */
  --fs-body:1.0625rem;                         /* 17px */
  --fs-h3:1.1875rem;                           /* 19px, subheads inside .prob .step .card .price-card */
  --fs-lead:1.3125rem;                         /* 21px, intro paragraphs only: .lead and .sub */
  --fs-h2:1.75rem;                             /* 28px */
  --fs-h1:clamp(1.875rem, 5.2vw, 2.75rem);     /* 30 to 44px */
  --fs-stat:clamp(2.25rem, 6vw, 3.5rem);       /* 36 to 56px */

  /* Space: three gap tiers so the page has chapters.
     These were 64 and 112. The tiers were sound; the arithmetic on top of them was not. A .band
     carried BOTH a 112px margin and 64px of internal padding, so an act meeting a band read as 176px
     of nothing and two bands in a row as 240px. The founder read the result as "weird huge vertical
     gaps between sections", which is exactly what it was. The fix is below at .band: a band now owns
     its space as padding and takes no margin at all, so one gap tier applies at any one boundary and
     these numbers mean what they say. */
  --gap-tight:24px;
  --gap-section:44px;
  --gap-act:72px;

  /* elevation: the z-axis the old sheet did not have */
  --e1:0 1px 2px rgba(21,32,27,.06), 0 4px 12px rgba(21,32,27,.05);
  --e2:0 2px 4px rgba(21,32,27,.08), 0 12px 32px rgba(21,32,27,.10);

  --radius:10px;
  --mono:ui-monospace,Consolas,Menlo,monospace;
  --sans:-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}

*{box-sizing:border-box}
/* 80px clears the tallest header variant (67px on the guides) and matches the offset the quiz
   engine already uses, so the site has one header-clearance number. Without it, #pricing parks
   the word "Pricing" behind the sticky header and the jump reads as broken. */
html{scroll-behavior:smooth;scroll-padding-top:80px}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{animation:none!important;transition:none!important}}
body{margin:0;font-family:var(--sans);font-size:var(--fs-body);line-height:1.62;color:var(--ink);background:var(--paper)}
img{max-width:100%}
a{color:var(--accent-dk)}
a:hover{color:var(--accent)}

/* weight carries hierarchy alongside size */
h1,h2,h3{line-height:1.18;text-wrap:balance;margin:0 0 .4em}
h1{font-size:var(--fs-h1);font-weight:800;letter-spacing:-.02em}
h2{font-size:var(--fs-h2);font-weight:700;letter-spacing:-.01em;margin:0 0 .45em}
/* Top margin only when something precedes it. With margin-top:0 the space above a chapter heading
   equalled the space below it, so proximity grouped every heading with the paragraph it was
   finishing rather than the one it was introducing. That is the most literal version of "hard to
   follow". An h2 that opens a section, article or band is still a first child and stays flush, so
   the 112px .act rhythm on the rewritten pages is untouched. */
* + h2{margin-top:1.9em}
h3{font-size:var(--fs-h3);font-weight:700}
p,li{max-width:68ch}
p{margin:.7em 0}
b,strong{font-weight:600}
.small{font-size:var(--fs-micro);color:var(--ink2);line-height:1.5;max-width:60ch}
.lead{font-size:var(--fs-lead);color:var(--ink2);line-height:1.5;max-width:46ch}
/* .sub is the older pages' name for the same role. Aliased rather than renamed across 14 files,
   with a wider measure because those pages use it for a full intro paragraph, not a one-line promise. */
.sub{font-size:var(--fs-lead);color:var(--ink2);line-height:1.5;max-width:58ch}
:where(a,button,summary,input):focus-visible{outline:3px solid var(--navy);outline-offset:2px;border-radius:4px}
/* Text only a screen reader gets. Lived in a page-local <style> on the home page until the catalog
   needed it on /exams/ too. */
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

.wrap{max-width:72rem;margin:0 auto;padding:0 20px}
.narrow{max-width:40rem}
/* A narrow SECTION inside a normal-width page kept .wrap's `margin:0 auto`, so it centred itself:
   the FAQ heading started 256px right of every other heading on the page and the reader's eye had
   to go looking for the start of the line. A narrow PAGE (main.wrap.narrow on the guides and the
   FAQ) is a different case and stays centred, because there is nothing wider to align to. The
   section keeps the reading measure by capping its children instead of itself. */
section.wrap.narrow{max-width:72rem}
section.wrap.narrow > *{max-width:40rem}
section{margin-top:var(--gap-section)}
section.act{margin-top:var(--gap-act)}
section > :first-child{margin-top:0}

/* ---------- skip link: the only bypass for a sighted keyboard or switch user ---------- */
.skip{position:absolute;left:-9999px;top:0;z-index:100;background:var(--navy);color:#fff;
  padding:12px 18px;border-radius:0 0 8px 0;font-weight:600;text-decoration:none}
.skip:focus{left:0}
/* a:hover would otherwise repaint the revealed link green on navy at about 1.5:1 */
.skip:hover,.skip:focus:hover{color:#fff}
main[tabindex="-1"]:focus{outline:none}

/* ---------- header: thin, one CTA ---------- */
.top{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.97);backdrop-filter:saturate(1.4) blur(6px);
  border-bottom:1px solid var(--rule)}
.top .wrap{display:flex;align-items:center;gap:18px;padding:9px 20px;min-height:56px}
.logo{font-weight:800;font-size:1.15rem;color:var(--ink);text-decoration:none;letter-spacing:-.02em}
.logo b{color:var(--navy)}
.nav{display:flex;gap:18px;margin-left:auto;align-items:center;font-size:.95rem}
/* :not(.btn) is load-bearing, not tidiness. `.nav a` is specificity (0,1,1) and `.btn` is (0,1,0),
   so without it the descendant rule wins and the header buy button renders --ink2 on --accent:
   dark grey on green at 1.31:1, effectively invisible, on every page. */
.nav a:not(.btn){text-decoration:none;color:var(--ink2)}
.nav a:not(.btn):hover{color:var(--ink)}
@media(max-width:820px){.nav .hide-m{display:none}}

/* ---------- buttons: the accent lives here and nowhere else ---------- */
.btn{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;
  background:var(--accent);color:#fff;border:none;border-radius:9px;
  padding:14px 26px;font:600 var(--fs-body)/1.25 var(--sans);cursor:pointer;text-decoration:none;
  text-align:center;min-height:48px;box-shadow:var(--e1);transition:background .15s,box-shadow .15s,transform .05s}
.btn:hover{background:var(--accent-dk);box-shadow:var(--e2);color:#fff}
.btn:active{transform:translateY(1px)}
.btn.big{padding:17px 34px;font-size:var(--fs-lead);min-height:60px}
.btn-sub{display:block;font-size:var(--fs-micro);font-weight:400;opacity:.92;margin-top:3px;letter-spacing:.01em}
/* The older pages write the label as inline text plus a price span, e.g.
   "Exam prep: <span data-price="legal">$99</span>". In a column flex container the text run and
   the span become two flex items and the label splits across two lines, with a dangling separator
   on the first. Only buttons that actually carry a .btn-sub want the column stack. A browser
   without :has() drops this rule and gets today's behaviour, so the fallback is the status quo. */
.btn:not(:has(.btn-sub)){flex-direction:row;flex-wrap:wrap;column-gap:.3em}
.btn.quiet{background:var(--navy)}
.btn.quiet:hover{background:#0f2740}
/* .ghost is the secondary action on the guide and FAQ pages. It must NOT be green: two green
   buttons side by side is the competing-CTA problem this stylesheet exists to fix. */
.btn.ghost{background:transparent;color:var(--navy);border:2px solid var(--navy);box-shadow:none;
  padding:12px 24px}
.btn.ghost:hover{background:var(--navy-wash);color:var(--navy);box-shadow:none}
/* .mini exists for the home page catalog, where 15 rows each need their own buy action. The full
   48px .btn would turn the catalog into a wall of green and break the rule that one thing per
   viewport reads as the action. 40px still clears the 24px WCAG 2.5.8 target floor comfortably. */
.btn.mini{padding:9px 16px;min-height:40px;font-size:.95rem;border-radius:7px;box-shadow:none;white-space:nowrap}
.btn.mini:hover{box-shadow:var(--e1)}
.textlink{color:var(--accent-dk);font-weight:600;text-decoration:underline;text-underline-offset:3px}
.btn.buy-pending{opacity:.95}

/* ---------- mobile buy bar ---------- */
.buybar{position:fixed;bottom:0;left:0;right:0;z-index:60;background:var(--paper);
  border-top:1px solid var(--rule);box-shadow:0 -4px 16px rgba(21,32,27,.10);
  padding:9px 14px;display:none;align-items:center;gap:12px}
.buybar .lbl{font-size:var(--fs-micro);color:var(--ink2);line-height:1.3}
.buybar .lbl b{display:block;font-size:var(--fs-body);color:var(--ink);font-weight:700}
.buybar .btn{margin-left:auto;padding:12px 20px;min-height:46px}
@media(max-width:820px){.buybar{display:flex}body{padding-bottom:76px}}

/* ---------- hero: asymmetric, proof on the right ---------- */
/* Longhand, not `padding:52px 0 8px`. The shorthand also set padding-inline to 0, and .hero is
   always used with .wrap, whose `padding:0 20px` it overrides on specificity ties by source order.
   So the hero, and only the hero, sat 20px left of every other section on desktop and went flush
   against the edge of the screen on a phone with no gutter at all. That is most of what "the
   alignment of different sections is all random" was pointing at. */
.hero{padding-top:52px;padding-bottom:8px}
.hero-grid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:44px;align-items:start}
@media(max-width:900px){.hero-grid{grid-template-columns:1fr;gap:28px}}
.kicker{font-size:var(--fs-micro);font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink3);margin:0 0 12px}
.hero h1{max-width:21ch}
.hero .lead{margin-bottom:22px}
.cta-row{display:flex;gap:20px;align-items:center;flex-wrap:wrap;margin:6px 0 14px}
.microtrust{display:flex;gap:8px 20px;flex-wrap:wrap;color:var(--ink2);font-size:var(--fs-micro);margin-top:14px}
.microtrust span{display:inline-flex;align-items:center;gap:6px}
.microtrust svg{flex:none;color:var(--ink3)}

/* ---------- stakes strip: the numbers, large ---------- */
.stakes{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px 28px;
  border-top:2px solid var(--ink);border-bottom:1px solid var(--rule);padding:26px 0;margin-top:var(--gap-section)}
.stat{padding:2px 0}
.stat .n{display:block;font-size:var(--fs-stat);font-weight:800;line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;color:var(--ink)}
.stat .n small{font-size:.42em;font-weight:700;letter-spacing:0}
.stat .l{display:block;font-size:var(--fs-micro);color:var(--ink2);margin-top:8px;max-width:22ch}

/* ---------- sample question: the proof artifact ---------- */
.qsample{background:var(--paper);border:1px solid var(--rule);border-radius:12px;box-shadow:var(--e2);overflow:hidden}
.qsample .qtop{background:var(--navy);color:#fff;padding:9px 18px;font-size:var(--fs-micro);font-weight:600;
  letter-spacing:.04em;display:flex;justify-content:space-between;gap:12px}
.qsample .qtop span{opacity:.85;font-weight:400}
.qsample .qbody{padding:20px 22px}
.qsample .stem{font-weight:600;margin:0 0 14px}
.qsample ol{list-style:none;margin:0;padding:0;counter-reset:opt}
.qsample ol li{counter-increment:opt;position:relative;padding:9px 12px 9px 40px;border:1px solid var(--rule);
  border-radius:7px;margin:7px 0;font-size:.97rem;max-width:none}
.qsample ol li::before{content:counter(opt,upper-alpha);position:absolute;left:12px;top:9px;
  font-weight:700;color:var(--ink3);font-size:.9rem}
.qsample ol li.right{border:2px solid var(--accent);background:var(--accent-wash);padding-left:39px}
.qsample ol li.right::before{color:var(--accent-dk)}
.qsample .why{border-top:1px solid var(--rule);margin-top:14px;padding-top:14px;font-size:.95rem;color:var(--ink2)}
.qsample .why p{margin:0 0 10px;max-width:none}

/* the citation chip: the single most repeated claim, made visible */
.cite{display:inline-block;font-family:var(--mono);font-size:var(--fs-micro);background:var(--navy-wash);
  border:1px solid #c8d6e4;color:#0f2740;border-radius:6px;padding:3px 9px;font-weight:600}

/* ---------- bands: real contrast, no false floors ---------- */
/* A band's padding IS the gap on both of its edges, and it takes no margin, so the space around a
   full bleed band is symmetric and equal to one act gap rather than a margin and a padding stacked.
   The rule below zeroes the following section's top margin for the same reason, and has to stay
   after `section.act` in this sheet: same specificity (0,1,1), so source order decides. */
.band{padding:var(--gap-act) 0;margin:0}
.band + section{margin-top:0}
.band.problem{background:var(--warn-wash);border-top:3px solid var(--warn);border-bottom:1px solid #ecdcbb}
.band.proof{background:var(--wash);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
/* --wash is also the footer fill, so a wash band closed by a 1px --rule edge is pixel-identical to
   the start of the footer: same fill, same rule, same 112px gap. Arriving after a big green button
   that reads as terminal, it makes a false floor and the reader stops before the pricing block.
   Full-bleed bands take the same 3px announcement weight .band.problem uses, in navy so the chapter
   reads as structure and never competes with the buy action. The two rounded .band.proof call-outs
   sit inside a .wrap and keep the hairline: a 3px top border on a 12px radius with no side borders
   leaves tapered corner stubs. */
main:not([class]) > .band.proof{border-top:3px solid var(--navy);border-bottom:1px solid var(--rule-strong)}

/* ---------- problem: no cards, heavy left rule ---------- */
.probs{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:32px;margin-top:26px}
.prob{border-left:4px solid var(--warn);padding:2px 0 2px 20px}
.prob h3{margin:0 0 6px}
.prob p{margin:0;color:var(--ink2)}

/* ---------- mechanism: numbered steps, not cards ---------- */
.steps{counter-reset:step;display:grid;gap:28px;margin-top:26px}
@media(min-width:820px){.steps{grid-template-columns:repeat(3,1fr);gap:36px}}
.step{counter-increment:step;position:relative;padding-top:44px}
.step::before{content:"0" counter(step);position:absolute;top:0;left:0;font-size:1.6rem;font-weight:800;
  color:var(--navy);letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.step::after{content:"";position:absolute;top:34px;left:0;width:34px;height:3px;background:var(--navy)}
.step h3{margin:0 0 6px}
.step p{margin:0;color:var(--ink2)}

/* ---------- cards (used sparingly now) ---------- */
.card{background:var(--paper);border:1px solid var(--rule);border-radius:var(--radius);padding:22px 24px;box-shadow:var(--e1)}
.card h3{margin-top:0}
.grid3{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px}
.tick{list-style:none;padding:0;margin:.6em 0}
.tick li{padding-left:26px;position:relative;margin:.5em 0}
.tick li::before{content:"";position:absolute;left:2px;top:.62em;width:11px;height:2px;background:var(--ink3)}

/* ---------- pricing ---------- */
.pricing{display:grid;grid-template-columns:1fr;gap:20px;align-items:stretch;margin-top:28px}
@media(min-width:900px){.pricing{grid-template-columns:repeat(3,1fr)}}
.price-card{border:1px solid var(--rule);border-radius:12px;padding:26px 24px;display:flex;flex-direction:column;
  background:var(--paper);box-shadow:var(--e1)}
.price-card.feature{border:2px solid var(--accent);box-shadow:var(--e2);padding:32px 28px;position:relative}
/* Scale only when the card is interior, so the growth is symmetric. On the SKU pages the feature
   card sits first, and scaling it there pushed it 7px past the page's left edge. */
@media(min-width:900px){.pricing > .price-card.feature:not(:first-child):not(:last-child){transform:scale(1.04);z-index:1}}
.price-card .flag{position:absolute;top:-13px;left:24px;background:var(--accent);color:#fff;font-size:var(--fs-micro);
  font-weight:700;padding:4px 13px;border-radius:20px;box-shadow:var(--e1)}
.price-card h3{margin:0 0 4px}
.price-card .who{font-size:var(--fs-micro);color:var(--ink3);margin:0 0 14px}
.price-line{display:flex;align-items:baseline;gap:9px;margin:10px 0 4px}
.price-line .now{font-size:var(--fs-stat);font-weight:800;line-height:1;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.price-line .per{font-size:var(--fs-micro);color:var(--ink3)}
.price-card .rising{font-size:var(--fs-micro);color:var(--warn);font-weight:600;margin:0 0 14px}
.price-card ul{flex:1}
.price-card .btn{margin-top:14px;width:100%}
.reassure{font-size:var(--fs-micro);color:var(--ink2);margin:10px 0 0;max-width:none}
.guarantee{border:2px solid var(--accent);border-radius:12px;padding:22px 26px;background:var(--accent-wash);margin:var(--gap-section) 0 0;max-width:60ch}
.guarantee h3{margin-top:0;color:var(--accent-dk)}
.guarantee p{max-width:none}

/* What every exam includes, said once above the catalog. The founder's note was that it "isnt
   obvious that you get two whole full mock tests per purchase", and it was not: the only place the
   page carried it was a pair of colour-named chips repeated on every row. */
.incl{list-style:none;margin:20px 0 0;padding:0;display:grid;gap:10px 28px}
@media(min-width:820px){.incl{grid-template-columns:repeat(2,1fr)}}
.incl li{margin:0;max-width:none;padding-left:26px;position:relative;font-size:.95rem;color:var(--ink2)}
.incl li b{color:var(--ink);font-weight:700}
.incl li::before{content:"";position:absolute;left:3px;top:.42em;width:6px;height:11px;
  border:solid var(--accent-dk);border-width:0 2.5px 2.5px 0;transform:rotate(42deg)}

/* ---------- comparison: column dominance, sticky labels ---------- */
/* tabindex="0" in the markup makes the scroll container reachable, since a keyboard user otherwise
   cannot pan a table that overflows. The focus ring has to be visible on the container itself. */
.tablewrap{overflow-x:auto;margin:24px 0;border:1px solid var(--rule);border-radius:12px;background:var(--paper)}
.tablewrap:focus-visible{outline:3px solid var(--navy);outline-offset:2px}
table{border-collapse:collapse;width:100%;font-size:.95rem}
caption{text-align:left;padding:14px 16px 0;font-size:var(--fs-micro);color:var(--ink3)}
th,td{padding:12px 14px;border-bottom:1px solid var(--rule);text-align:left;vertical-align:top}
thead th{font-size:var(--fs-micro);text-transform:uppercase;letter-spacing:.05em;color:var(--ink3);font-weight:700;
  background:var(--wash);white-space:nowrap}
tbody th[scope=row]{font-size:1rem;font-weight:600;color:var(--ink2);text-transform:none;letter-spacing:0;
  position:sticky;left:0;background:var(--paper);white-space:nowrap}
/* Column 2 is "BCINprep" on a comparison table, so the accent wash is doing real work there. On the
   catalog it is "Questions", and the same rules painted a green stripe the full height of the table:
   the eye went to a question count instead of the exam name or the price, and it competed with the
   green buy button in the total bar. Green means buy on this site, in four other places in this
   sheet. :not(.catalog) keeps the rule where it belongs. */
.cmp:not(.catalog) thead th:nth-child(2),.cmp:not(.catalog) tbody td:nth-child(2){background:var(--accent-wash)}
.cmp:not(.catalog) thead th:nth-child(2){color:var(--accent-dk);border-top:3px solid var(--accent)}
.cmp:not(.catalog) tbody tr:last-child td:nth-child(2){border-bottom:3px solid var(--accent)}
.cmp:not(.catalog) td:nth-child(2){font-weight:600;color:var(--ink)}
td.no{color:var(--ink3)}
tr:last-child td,tr:last-child th{border-bottom:none}

/* The home page catalog carries a price and an Add button per row, so those two columns are pinned
   right and never wrap. The exam name is what the reader scans; everything else is a fixed column.
   Columns are addressed by class, not by :nth-child, because the column order has changed twice and
   each time an nth-child rule silently landed on the wrong column: the accent wash meant for a
   comparison table painted a green stripe down "Questions", and the mobile hide rules had to be
   renumbered by hand. A class cannot drift when a column moves. */
.catalog td.price,.catalog th.price{font-variant-numeric:tabular-nums;font-weight:700;color:var(--ink);
  white-space:nowrap;text-align:right;width:1%}
.catalog td.add,.catalog th.add{text-align:right;white-space:nowrap;width:1%;padding-left:6px}
.catalog td.who{color:var(--ink2)}

/* What you get, under the name where it reads as a sentence. This replaced a "Papers" column that
   drew a Red chip and a Blue chip on all fifteen rows: identical on every row, so it carried no
   information a reader could act on, and it never said anywhere that a paper is a whole mock exam. */
/* .rowsub is the /exams/ catalog's own sub-line (topic and delta counts). It had no rule at all in
   this sheet, so it ran on as inline text in the row header at full body size. */
.catalog .ex-inc,.catalog .rowsub{display:block;font-weight:400;font-size:var(--fs-micro);
  color:var(--ink3);margin-top:2px;white-space:normal}
.catalog tbody tr:hover td,.catalog tbody tr:hover th[scope=row]{background:var(--wash)}

/* catalog: grouped rows so 15 exams read as four short lists, not one long one */
.catalog .grp th{background:var(--navy);color:#fff;font-size:var(--fs-micro);font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;padding:8px 14px;position:static}
/* The flex row lives INSIDE the cell, never on it: the cell carries colspan="4" and display:flex
   would take it out of table layout and drop the colspan. chooser.js builds this wrapper, so a
   reader without JavaScript just gets the plain heading text it always had.
   The cell's right padding (14px, 10px on mobile) matches td.add's, so the track button and the row
   Add buttons share one right edge and the eye follows a single column down the table. */
.grp-row{display:flex;align-items:center;flex-wrap:wrap;gap:2px 12px}
.catalog .grp-n{text-transform:none;letter-spacing:0;font-weight:400;opacity:.85}
/* The two SKU landing pages reuse .catalog for a topic-coverage table: same grouped rows, but no
   data-pick, so nothing is buyable and column 2 is a plain question count. It is the one place a
   :nth-child column rule is still right, because that table has no per-column classes to hang it on. */
.catalog:not([data-pick]) tbody td:nth-child(2){font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.catalog:not([data-pick]) thead th:nth-child(2){text-align:right}
.catalog tbody th[scope=row]{white-space:normal;min-width:13rem;color:var(--ink)}
/* At 390px the pinned row header ate 59% of the window, leaving the data it labels unreadable. */
@media(max-width:640px){
  .catalog tbody th[scope=row]{min-width:8rem}
  .catalog th,.catalog td{padding:10px 10px}
  .catalog .grp th{padding:8px 10px}
  /* The track name and its button share the first line, the description drops to its own. `order`
     moves the button visually only; it is the sole focusable thing in the row, so tab order is
     unaffected. flex-basis:100% is what forces the wrap: `display:block` on a flex item does
     nothing, so the old rule silently stopped working the moment the bar became a flex row. */
  .catalog .grp-n{flex:1 0 100%;order:3;margin:2px 0 0}
  .add-all{order:2}

  /* Measured at 390px before this rule: the table was 526px inside a 348px container, so "Who sits
     it" and the PRICE were both entirely off screen, and the prose column wrapped to nine lines
     which, because cells in a row share a height, set every visible row to 144px against 61px on
     desktop. An unreadable column was doubling the height of the readable ones and pushing the price
     out of a pricing table. Dropping it leaves exam, price and Add, which is everything a phone
     reader needs to buy. */
  .catalog .who{display:none}
}

/* ---------- catalog cart ----------
   An Add button per exam, an Add all per track, the cart under the table and the compact bar that
   follows the reader down it. Every one of these controls is injected by assets/chooser.js, so a
   reader without JavaScript sees exactly the table they always saw rather than dead buttons.

   These are --navy, not --accent. Fifteen green buttons in a column would each read as THE buy
   action, and the rule this sheet exists to protect is that green means buy and appears once per
   viewport. Adding to a cart is not buying: the green belongs on the checkout button in the cart,
   which is where the money actually moves. */
/* Filled amber, its own hue. Two earlier passes failed to make this column visible: outlined navy
   read as body-weight text on a white row, and filled navy was stronger but still the same colour
   as every heading, rule and track bar on the page, so it read as more structure. Amber is the only
   thing on the page wearing it, which is what makes the column catchable at a glance. */
.add-btn{appearance:none;font:inherit;font-size:var(--fs-micro);font-weight:700;line-height:1;
  padding:10px 17px;min-height:40px;border-radius:8px;cursor:pointer;white-space:nowrap;
  border:2px solid var(--add);background:var(--add);color:#fff;box-shadow:var(--e1);
  transition:background .12s,color .12s,border-color .12s,box-shadow .12s}
/* inline-flex + gap centres the glyph against the label without per-glyph nudging. */
.add-btn .ab-face{display:inline-flex;align-items:center;gap:7px}
.add-btn .ab-face::before{content:"+";font-size:1.25em;line-height:1;margin-top:-1px}
.add-btn:hover{background:var(--add-dk);border-color:var(--add-dk);box-shadow:var(--e2)}
/* Added is the QUIET state, and neutral rather than amber: the work is done, the row already carries
   a navy tint, and this control should stop competing with the fourteen that still want pressing.
   Filled means "press me", outlined means "already yours", which is the opposite of the usual
   selected-is-louder pattern and is right here, because the job is to pull the eye toward what has
   NOT been added yet. It also means the amber that remains is exactly the set still worth pressing. */
.add-btn.is-in{background:var(--paper);border-color:var(--rule-ui);color:var(--ink2);box-shadow:none}
/* Neutral tick, not a green one. A green "done" tick is the obvious choice and is deliberately not
   taken: this sheet's one hard rule is that green appears only on the control that takes money, and
   a future reader finding green here would be right to remove it. The tick shape carries "done"
   without needing a colour to say it. */
.add-btn.is-in .ab-face::before{content:"";width:5px;height:9px;margin:0 1px 3px 0;
  border:solid var(--ink2);border-width:0 2px 2px 0;transform:rotate(42deg)}
.add-btn.is-in:hover{background:var(--danger-wash);border-color:var(--danger);color:var(--danger)}
.add-btn.is-in:hover .ab-face::before{border-color:var(--danger)}
/* The row control is a state toggle, so it says so. */
/* The same amber on the navy bar, so the track control and the row controls read as one column of
   one kind of thing. It carries a white ring because amber against navy is only about 2.5:1, under
   the 3:1 WCAG 1.4.11 wants for a boundary that identifies a control; the ring is what separates
   the button from the bar, and the amber is what identifies it as an add. */
.add-all{appearance:none;font:inherit;font-size:var(--fs-micro);font-weight:700;line-height:1;
  display:inline-flex;align-items:center;gap:6px;
  margin-left:auto;padding:7px 14px;min-height:32px;border-radius:20px;cursor:pointer;
  white-space:nowrap;text-transform:none;letter-spacing:0;
  border:2px solid #fff;background:var(--add);color:#fff;
  transition:background .12s,color .12s,border-color .12s}
.add-all::before{content:"+";font-size:1.25em;line-height:1;margin-top:-1px}
.add-all:hover{background:var(--add-dk)}
/* Whole track added: quiet again, and the plus would contradict a button that now says Remove all. */
.add-all.is-in{background:transparent;color:#fff;border-color:rgba(255,255,255,.7)}
.add-all.is-in::before{content:none}
.add-all.is-in:hover{background:rgba(255,255,255,.16);border-color:#fff}
.catalog tbody tr.is-picked td,
.catalog tbody tr.is-picked th[scope=row]{background:var(--navy-wash)}
.catalog tbody tr.is-picked th[scope=row]{color:var(--ink)}

/* The cart itself: what you added, by name, each line removable. The bar above carries the same
   arithmetic in one line; this is the part that answers "what have I actually got in here". */
.cart{border:1px solid var(--rule-strong);border-radius:12px;background:var(--paper);
  box-shadow:var(--e1);padding:20px 22px;margin-top:var(--gap-tight)}
.cart.is-on{border-color:var(--navy)}
.cart-h{margin:0 0 10px;font-size:var(--fs-h3)}
.cart-empty{margin:0;color:var(--ink2);font-size:var(--fs-micro);max-width:none}
.cart-lines{list-style:none;margin:0;padding:0}
.cl{display:flex;align-items:center;gap:12px;padding:9px 0;border-bottom:1px solid var(--rule);
  max-width:none}
.cl:last-child{border-bottom:none}
.cl-name{flex:1;min-width:0;font-weight:600}
.cl-price{font-variant-numeric:tabular-nums;font-weight:700;white-space:nowrap}
.cl-x{appearance:none;font:inherit;font-size:var(--fs-micro);line-height:1;padding:7px 10px;
  min-height:34px;border-radius:6px;cursor:pointer;white-space:nowrap;
  border:1px solid var(--rule-ui);background:var(--paper);color:var(--ink2)}
.cl-x:hover{border-color:var(--danger);color:var(--danger)}
.bk-cart{margin-top:14px;border-top:2px solid var(--ink);padding-top:14px}
.bk-cart .bk-n{font-size:var(--fs-micro);color:var(--ink2);font-weight:400}

/* ---------- FAQ ---------- */
details{border:1px solid var(--rule);border-radius:9px;padding:0;margin:10px 0;background:var(--paper)}
summary{font-weight:600;cursor:pointer;padding:14px 46px 14px 18px;position:relative;list-style:none}
summary::-webkit-details-marker{display:none}
summary::after{content:"+";position:absolute;right:18px;top:12px;font-size:1.3rem;font-weight:400;color:var(--ink3)}
details[open]{border-left:3px solid var(--navy)}
details[open] summary::after{content:"\2212"}
details > :not(summary){padding:0 18px 16px}
details p{margin-top:0}

.notice{background:var(--warn-wash);border:1px solid #ecdcbb;border-radius:9px;padding:14px 18px;font-size:.95rem}
.badge{display:inline-block;background:var(--navy-wash);color:#0f2740;font-size:var(--fs-micro);font-weight:700;
  padding:2px 10px;border-radius:12px}

footer{border-top:1px solid var(--rule);margin-top:var(--gap-act);padding:36px 0;color:var(--ink2);font-size:.9rem;background:var(--wash)}
footer a:not(.btn){color:var(--ink2)}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:22px}
.foot-grid b{color:var(--ink)}
/* WCAG 2.2 SC 2.5.8. Below 820px .nav .hide-m removes the whole top nav, so these footer links are
   the only navigation on a phone, and they were 23px tall with no gap. Padding buys the target;
   margin buys the separation between adjacent targets, which padding cannot. Not display:block:
   the existing <br> separators would each then produce an empty line. */
.foot-grid a[href^="/"]{display:inline-block;padding:4px 0;margin:2px 0;line-height:1.4}

/* form controls: the border is the control, so it needs the 3:1 token */
input,select,textarea{border:1px solid var(--rule-ui);border-radius:8px;padding:10px 12px;
  font:400 var(--fs-body)/1.4 var(--sans);color:var(--ink);background:var(--paper);min-height:44px}
input::placeholder{color:var(--ink3)}

/* ---------- quiz engine ---------- */
.quiz{max-width:44rem;margin:0 auto}
.qhead{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:12px}
.qhead .timer{font-family:var(--mono);font-weight:700;padding:5px 13px;border:1px solid var(--rule-ui);border-radius:8px;
  font-variant-numeric:tabular-nums}
.qhead .timer.low{color:var(--danger);border-color:var(--danger)}
.qprog{flex:1;height:8px;background:var(--wash2);border-radius:6px;overflow:hidden;min-width:120px}
.qprog i{display:block;height:100%;background:var(--accent)}
.qcard{border:1px solid var(--rule);border-radius:12px;padding:24px;background:var(--paper);box-shadow:var(--e1)}
.qstem{font-size:var(--fs-lead);font-weight:600;line-height:1.4}
.qopts{list-style:none;padding:0;margin:16px 0}
.qopts li{margin:9px 0;max-width:none}
.qopts button{width:100%;text-align:left;padding:13px 16px;border:1px solid var(--rule-ui);border-radius:8px;
  background:var(--paper);cursor:pointer;font:400 1rem/1.5 var(--sans);transition:border-color .15s,background .15s}
.qopts button:hover{border-color:var(--navy)}
.qopts button.sel{border:2px solid var(--navy);background:var(--navy-wash);padding:12px 15px}
.qopts button.right{border:2px solid var(--accent);background:var(--accent-wash);padding:12px 15px}
.qopts button.wrong{border:2px solid var(--danger);background:var(--danger-wash);padding:12px 15px}
.qexp{border-left:3px solid var(--accent);background:var(--wash);padding:14px 18px;border-radius:0 8px 8px 0;margin-top:14px}
.qexp p{max-width:none}
.qnav{display:flex;gap:10px;margin-top:18px;flex-wrap:wrap;align-items:center}
.qnav .spacer{flex:1}
.qnav .btn{min-height:44px;padding:11px 20px}
.qgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(40px,1fr));gap:6px;margin:16px 0}
.qgrid button{padding:9px 0;border:1px solid var(--rule-ui);border-radius:6px;background:var(--paper);cursor:pointer;
  font-size:.85rem;min-height:40px}
.qgrid button.done{background:var(--navy-wash);border-color:var(--navy)}
.qgrid button.flagged{border-color:var(--warn);background:var(--warn-wash)}
/* Inset ring, so outline stays reserved for :focus-visible and the current-question state stacks
   with .done and .flagged instead of overwriting their fill. */
.qgrid button.cur{box-shadow:inset 0 0 0 2px var(--navy);font-weight:700}
.result-big{font-size:var(--fs-stat);font-weight:800;font-variant-numeric:tabular-nums;line-height:1}
.result-pass{color:var(--accent-dk)}
.result-fail{color:var(--danger)}
.topic-bar{display:flex;align-items:center;gap:12px;margin:8px 0}
.topic-bar .bar{flex:1;height:10px;background:var(--wash2);border-radius:6px;overflow:hidden}
.topic-bar .bar i{display:block;height:100%;background:var(--accent)}
.topic-bar .lbl{min-width:200px;font-size:.9rem}
.topic-bar .pct{font-family:var(--mono);font-size:.85rem;min-width:52px;text-align:right;font-variant-numeric:tabular-nums}

/* ---------- the shared basket ----------
   One set of exams, priced by window.BCP.quote, with one buy action under it. assets/chooser.js
   builds it, and both the chooser's result panel (.bk-panel) and the catalog's running total
   (.bk-bar) are the same component, so the two can never quote different arithmetic. The single
   green .btn inside it is the buy action, and the rule this stylesheet exists to protect is that
   green means buy and nothing else. */
/* Lines inside .bk-say are hidden with the hidden attribute when they have nothing to say, so no
   rule below may set `display` on one of them: the UA's [hidden]{display:none} loses to any author
   declaration of equal specificity, and a stale total would come back the moment a reader emptied
   their selection. The bar lays out with flex on the container instead. */
.bk-n{margin:0;font-weight:600;max-width:none}
.bk-total{margin:.2em 0 0;font-size:var(--fs-lead);max-width:none}
.bk-total b{font-size:var(--fs-stat);font-weight:800;line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;display:inline-block;vertical-align:-2px}
.bk-total-n{color:var(--ink2)}
.bk-cmp{margin:.5em 0 0;font-size:var(--fs-micro);color:var(--ink2);max-width:56ch}
.bk-buy{margin:18px 0 0;max-width:none}
.bk-buy .btn{width:100%}
.bk-refund{margin:.6em 0 0;font-size:var(--fs-micro);color:var(--ink2);max-width:none}
/* panel variant: the chooser's result, stacked, the big number carrying the weight */
.bk-panel{margin-top:24px}

/* The catalog's bar. .tablewrap is a scroll container, so a sticky child of it would pin to the
   table's own bottom edge and never move; .cat-pick wraps the table and the bar together and is the
   sticky context instead. It only goes sticky once something is ticked, so an untouched page never
   carries a floating bar that says nothing. */
.cat-pick{position:relative}
/* display:none, not just "not sticky". The bar sits immediately before the cart in the DOM, so an
   inactive bar left in normal flow rendered its total and its green button about 100px above the
   cart's identical total and identical green button. Taking it out of flow also removes the ~90px
   of blank space it otherwise reserved between the table and the cart. */
.cat-bar{display:none;margin:12px 0 0}
.cat-bar.is-on{display:block;position:sticky;bottom:14px;z-index:40}
/* Measured at 390px with two exams ticked: the cart bar and the site buy bar together occupied 221px,
   26% of the viewport, with two green buttons, and the lower and more thumb reachable one bought a
   single exam at $149 rather than the two at $198 just selected. While the cart has anything in it,
   it is the only buy action on screen. */
/* Keyed to the cart having contents, not to the bar being up. The bar now stands down whenever the
   cart panel is on screen, and keying this to the bar meant the site's own buy button came back at
   exactly that moment: a second green button quoting one exam at $149 while the cart beside it
   quoted the two you actually added at $198. */
body:has(.cart.is-on) .buybar{display:none}
.bk-bar{display:flex;flex-wrap:wrap;gap:10px 20px;align-items:center;justify-content:space-between;
  border:1px solid var(--rule-strong);border-radius:12px;background:var(--paper);box-shadow:var(--e2);
  padding:12px 16px}
.bk-bar .bk-say{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 10px;min-width:0}
.bk-bar .bk-n{font-size:var(--fs-micro);color:var(--ink2)}
.bk-bar .bk-total{margin:0;font-size:var(--fs-body)}
.bk-bar .bk-total b{font-size:var(--fs-h2);vertical-align:-1px}
.bk-bar .bk-cmp{flex:1 0 100%;margin:.25em 0 0}
.bk-bar .bk-buy{margin:0;flex:none}
.bk-bar .bk-buy .btn{width:auto}
/* Below 820px the fixed .buybar owns the bottom of the window, so the basket bar sits above it and
   never lands on top of the buy button that is already there. */
@media(max-width:820px){
  .cat-bar.is-on{bottom:82px}
  .bk-bar{padding:11px 13px;gap:9px}
  .bk-bar .bk-say,.bk-bar .bk-buy{flex:1 0 100%}
  .bk-bar .bk-buy .btn{width:100%;padding:11px 18px;min-height:46px}
}

/* ---------- checkout guide (the exam chooser) ----------
   assets/chooser.js enhances <div id="exam-chooser">; tools/render-chooser.js writes the same
   mapping into it as static HTML for crawlers and for anyone without JavaScript.
   Every control in here is --navy. The single green .btn in the result panel is the buy action, and
   the rule this stylesheet exists to protect is that green means buy and nothing else. */
.ec,.ec-static{background:var(--paper);border:1px solid var(--rule);border-radius:12px;
  padding:24px 26px;box-shadow:var(--e1);max-width:46rem}
/* The fallback is three tables rather than a form, so it gets the wider measure. */
.ec-static{max-width:58rem}
.ec-intro{margin:0 0 20px;color:var(--ink2)}

.ec-fs{border:0;margin:0 0 22px;padding:0;min-width:0}
.ec-fs[hidden]{display:none}
.ec-fs legend{padding:0;font-weight:700;font-size:var(--fs-h3);line-height:1.3}
.ec-fs-hint{margin:.3em 0 .9em;max-width:52ch}
.ec-hint{display:block;font-size:var(--fs-micro);color:var(--ink3);line-height:1.45}
/* The label row carries the touch target. site.css gives every input a 44px min-height and 10px of
   padding, which stretches a radio into an oval, so the control itself opts out. */
.ec-opt{display:flex;gap:11px;align-items:flex-start;padding:10px 13px;margin:7px 0;
  border:1px solid var(--rule-ui);border-radius:8px;cursor:pointer;min-height:44px;max-width:none}
.ec-opt:hover{border-color:var(--navy);background:var(--navy-wash)}
/* The ring goes on the whole row, so the 18px control does not get a second one inside it. */
.ec-opt:focus-within{outline:3px solid var(--navy);outline-offset:2px}
.ec-opt input{min-height:0;width:18px;height:18px;padding:0;margin:3px 0 0;border:0;flex:none;accent-color:var(--navy)}
.ec-opt input:focus-visible{outline:none}
.ec-opt-t b{font-weight:600}
.ec-actions{margin:4px 0 0}
.ec-go,.ec-add-btn{background:var(--navy);color:#fff;border:0;border-radius:8px;cursor:pointer;
  font:600 var(--fs-body)/1.2 var(--sans);padding:12px 22px;min-height:46px}
.ec-go:hover,.ec-add-btn:hover{background:#0f2740}

.ec-result{border-top:1px solid var(--rule);margin-top:26px;padding-top:22px}
.ec-result[hidden]{display:none}
.ec-h{margin:0 0 14px}
.ec-h:focus{outline:3px solid var(--navy);outline-offset:3px;border-radius:4px}
.ec-list{list-style:none;padding:0;margin:0 0 18px}
.ec-list[hidden]{display:none}
.ec-empty{margin:0 0 18px;color:var(--ink2)}
.ec-empty[hidden]{display:none}
.ec-list li{display:flex;gap:14px;align-items:flex-start;justify-content:space-between;
  padding:12px 0;border-bottom:1px solid var(--rule);max-width:none}
.ec-list li:last-child{border-bottom:0}
.ec-nm b{display:block}
.ec-q{display:block;font-size:var(--fs-micro);color:var(--ink3);font-variant-numeric:tabular-nums}
.ec-why{display:block;font-size:var(--fs-micro);color:var(--ink2);max-width:52ch;margin-top:3px}
.ec-rm{background:transparent;color:var(--navy);border:1px solid var(--rule-ui);border-radius:8px;
  cursor:pointer;font:600 var(--fs-micro)/1.2 var(--sans);padding:8px 14px;min-height:36px;flex:none}
.ec-rm:hover{background:var(--navy-wash);border-color:var(--navy)}
.ec-add{border-top:1px solid var(--rule);padding-top:16px}
.ec-add label{display:block;font-size:var(--fs-micro);font-weight:600;color:var(--ink2);margin-bottom:6px}
.ec-add-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.ec-add-row select{flex:1;min-width:14rem;max-width:26rem}

/* The totals, the saving and the buy button used to live here. They are .bk-* now, shared with the
   catalog, because the founder's rule is that a hand-picked set and a recommended set end in the
   same summary and the same buy action. .ec-refund stays: tools/render-chooser.js still writes it
   into the no-JS fallback. */
.ec-refund{margin:.6em 0 0;font-size:var(--fs-micro);color:var(--ink2);max-width:none}
.ec-h4{margin:24px 0 6px;font-size:var(--fs-h3)}
.ec-notes{margin:0;padding-left:20px}
.ec-notes li{font-size:var(--fs-micro);color:var(--ink2);margin:.45em 0;max-width:56ch}
/* Said once, near the result. The chooser is a starting point and has to look like one. */
.ec-honest{margin:20px 0 0;padding:14px 16px;background:var(--wash);border-left:3px solid var(--navy);
  border-radius:0 8px 8px 0;font-size:var(--fs-micro);color:var(--ink2);max-width:none}
.ec-honest b{color:var(--ink)}

.ec-static > :first-child{margin-top:0}
.ec-static h4{margin:24px 0 6px;font-size:var(--fs-h3)}
.ec-static .tablewrap{margin:10px 0 0}
.ec-static table{font-size:.92rem}
.ec-static td b{font-weight:600}
@media(max-width:640px){
  .ec,.ec-static{padding:20px 16px}
  .ec-list li{flex-direction:column;gap:9px}
}
