
/* InkBiology, in the house style.
 *
 * This library was written for a hostname of its own and styled for one: a
 * cream page, a serif body, its own component vocabulary. It joined an origin
 * that already had two libraries on it, and next to them it read as a
 * different publisher's site -- the same seven brand tokens declared at the
 * top of this file and then not used, a body face nobody else uses, and
 * headings asking for Poppins when no Poppins was served.
 *
 * The class names below are the ones this build already emits, unchanged.
 * What changed is what they look like: the ground, the type, the surfaces and
 * the radii are the ones physics and maths use, so a reader moving between
 * the three moves between subjects rather than between websites.
 */
:root{--ink-bg:#0D1B2A;--ink-text:#F5F5F5;--ink-muted:#84919F;--ink-stroke:#6E7D8C;--ink-cyan:#38B6FF;--ink-purple:#A56EFF;--ink-coral:#EF476F;--ink-amber:#FFB703;--ink-success:#2EA043;--ink-card:rgba(255,255,255,.035);--ink-edge:rgba(245,245,245,.13);--ink-hair:rgba(245,245,245,.09);--navy:var(--ink-bg);--ink:var(--ink-text);--cyan:var(--ink-cyan);--amber:var(--ink-amber);--coral:var(--ink-coral);--grey:var(--ink-stroke);--greytx:var(--ink-muted);--bg:var(--ink-bg);--card:var(--ink-card);--edge:var(--ink-edge);--hair:var(--ink-hair);--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--space-5:1.5rem;--space-6:2rem;--space-7:3rem;--space-8:4rem;--subject-accent:var(--ink-muted)}[data-subject="physics"]{--subject-accent:var(--ink-cyan)}[data-subject="maths"]{--subject-accent:var(--ink-purple)}[data-subject="biology"]{--subject-accent:var(--ink-coral)}html{-webkit-text-size-adjust:100%}.brandrow{display:flex;align-items:center;gap:.6rem;min-width:0}.brandrow .wmsvg{display:block}.brandsub{display:flex;align-items:center;text-decoration:none;margin-right:.15rem}.brandpar{display:flex;align-items:center;text-decoration:none;padding-left:.6rem;border-left:1px solid var(--ink-edge);opacity:.85}.brandpar:hover,.brandpar:focus-visible{opacity:1}@media(max-width:420px){.brandpar{padding-left:.42rem}.brandpar .wmsvg{height:13px}.brandrow{gap:.42rem}}nav.top a[aria-current]{color:var(--subject-accent);opacity:1;border-bottom:2px solid var(--subject-accent)}nav.top [aria-disabled=true]{color:var(--ink-muted);cursor:default;display:inline-flex;align-items:baseline;gap:.32rem}nav.top [aria-disabled=true] .soon{font-size:.62rem;letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--ink-edge);border-radius:999px;padding:.06rem .34rem;white-space:nowrap}.navbtn{display:none;align-items:center;justify-content:center;width:44px;height:44px;border:1px solid var(--ink-edge);border-radius:12px;background:transparent;color:var(--ink-text);cursor:pointer;flex:none}.navbtn svg{width:20px;height:20px}@media(max-width:720px){.navbtn{display:inline-flex}header.site nav.top{display:none;order:3;width:100%;flex-wrap:wrap;gap:.2rem .9rem;padding:.5rem 0 .1rem;border-top:1px solid var(--ink-hair);margin-top:.55rem}header.site nav.top.open{display:flex}header.site nav.top a{padding:.55rem 0;min-height:44px;display:inline-flex;align-items:center}}@media(prefers-reduced-motion:no-preference){.navbtn{transition:border-color 140ms ease}}.fgroups{display:grid;gap:var(--space-5) var(--space-6);grid-template-columns:repeat(4,minmax(0,1fr));margin:0 0 var(--space-5)}@media(max-width:900px){.fgroups{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:520px){.fgroups{grid-template-columns:1fr}}.fgroup h2{font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-muted);margin:0 0 .5rem;font-weight:600}.fgroup ul{list-style:none;margin:0;padding:0;display:grid;gap:.34rem}.fgroup a{color:var(--ink-text);text-decoration:none;font-size:.88rem}.fgroup a:hover,.fgroup a:focus-visible{text-decoration:underline;text-underline-offset:3px}.beta{display:inline-block;font-size:.66rem;letter-spacing:.06em;text-transform:uppercase;border:1px solid var(--ink-edge);border-radius:999px;padding:.1rem .42rem;color:var(--ink-muted);vertical-align:.14em;margin-left:.45rem;font-weight:600}
:root{--wtext:42rem;--wpanel:47rem;--wfig:58rem}
@font-face{font-family:'Poppins';font-weight:400;font-style:normal;font-display:swap;
src:url('/biology/assets/fonts/poppins-400.woff') format('woff')}
@font-face{font-family:'Poppins';font-weight:500;font-style:normal;font-display:swap;
src:url('/biology/assets/fonts/poppins-500.woff') format('woff')}
@font-face{font-family:'Poppins';font-weight:700;font-style:normal;font-display:swap;
src:url('/biology/assets/fonts/poppins-700.woff') format('woff')}
/* InkGlyphs is a small face carrying the symbols Poppins does not have: the
   Greek block, the superscript and subscript digits, the arrow, the tick, the
   proportional and inequality signs. The unicode-range is the list of what is
   actually in the file, copied from the physics build because the two
   libraries serve the same font binary, and it is not decoration.
   Without it a browser has to download both weights of InkGlyphs on every page
   whether or not a single character on that page will ever be set in it, and
   more importantly the font is then a candidate for every character in the
   body copy: any codepoint it happens to contain gets taken from InkGlyphs
   rather than Poppins, and a paragraph can end up with one letter drawn from a
   different face at different metrics. With the range declared, the browser
   fetches the face only for pages that use one of these characters and uses it
   only for those characters. */
@font-face{font-family:'InkGlyphs';font-weight:400;font-style:normal;font-display:swap;
src:url('/biology/assets/fonts/inkglyphs-400.woff') format('woff');
unicode-range:U+0370-03FF,U+221D,U+2264-2265,U+00B2-00B3,U+00B9,U+2070-2079,U+207B,U+2080-2089,U+0127,U+2096,U+2192,U+207A,U+2153-2154,U+2713,U+2090}
@font-face{font-family:'InkGlyphs';font-weight:700;font-style:normal;font-display:swap;
src:url('/biology/assets/fonts/inkglyphs-700.woff') format('woff');
unicode-range:U+0370-03FF,U+221D,U+2264-2265,U+00B2-00B3,U+00B9,U+2070-2079,U+207B,U+2080-2089,U+0127,U+2096,U+2192,U+207A,U+2153-2154,U+2713,U+2090}
/* The figure palette. The drawing engine writes class names onto every line,
   shape and label and never writes a colour, so without these rules a figure
   renders in the browser default: black text on the navy figure panel, and
   geometry with no stroke at all. The whole library shipped that way once,
   because every gate inspected the SVG string rather than the rendering.
   Gate 12 now proves each class a figure uses has a rule here. */
.figsvg .sk-ink{stroke:var(--ink)}.figsvg .sk-cyan{stroke:var(--cyan)}
.figsvg .sk-grey{stroke:var(--grey)}.figsvg .sk-amber{stroke:var(--amber)}
.figsvg .sk-coral{stroke:var(--coral)}.figsvg .sk-bg{stroke:var(--bg)}
.figsvg .sk-greytx{stroke:var(--greytx)}
.figsvg .fl-ink{fill:var(--ink)}.figsvg .fl-cyan{fill:var(--cyan)}
.figsvg .fl-grey{fill:var(--grey)}.figsvg .fl-amber{fill:var(--amber)}
.figsvg .fl-coral{fill:var(--coral)}.figsvg .fl-bg{fill:var(--bg)}
.figsvg .fl-greytx{fill:var(--greytx)}
.figsvg .tx-ink{fill:var(--ink)}.figsvg .tx-cyan{fill:var(--cyan)}
.figsvg .tx-grey{fill:var(--greytx)}.figsvg .tx-amber{fill:var(--amber)}
.figsvg .tx-coral{fill:var(--coral)}.figsvg .tx-bg{fill:var(--bg)}
/* InkGlyphs first, then Poppins, and no system-ui anywhere in the list. This
   is the physics stack, and figure text is the one place where the order
   matters for correctness rather than for taste: the drawing engine positions
   every label by computing its width from the font it expects, so a label that
   renders in a face with different metrics lands in the wrong place, overlaps
   the geometry next to it, or runs outside the viewBox. system-ui was the real
   hazard, because it resolves to a different font on every operating system
   and guaranteed that the drawing was measured against one face and drawn in
   another. */
.figsvg text{font-family:'InkGlyphs','Poppins',sans-serif}
.figsvg rect.fl-bg[stroke-width]{stroke:var(--ink)}
*{box-sizing:border-box}
html{color-scheme:dark}
body{margin:0;min-height:100vh;display:flex;flex-direction:column;
background:radial-gradient(1100px 520px at 50% -180px,rgba(56,182,255,.055),transparent 62%) var(--bg);
color:var(--ink);font-family:'Poppins','InkGlyphs',sans-serif;font-weight:400;
/* 1.05rem, not 16.5px, and the two are not the same thing however close the
   numbers look. A px body size ignores the reader's own root font size, so a
   reader who has set their browser to 20px because they need to gets 16.5px
   from this library and 21px from its two siblings, on the same origin, in the
   same session. 1.05rem is what physics and maths set and it scales with them.
   Nothing measured off the old value: the one other 16.5 in this codebase is a
   recombination frequency in a genetics figure and a line height in the PDF
   workbook generator, neither of which reads this sheet. */
font-size:1.05rem;line-height:1.68;
padding-bottom:calc(72px + env(safe-area-inset-bottom))}
a{color:var(--cyan)}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{
outline:2px solid var(--cyan);outline-offset:2px;border-radius:3px}
.skip{position:absolute;left:-9999px}
/* 12px, not .4rem. The skip link is a button in every way that matters -- it
   is the first thing a keyboard reader reaches on the page and the thing they
   press -- and the shared radius scale puts ordinary buttons at 10 to 12px.
   .4rem computed to 6.4px, which is tight enough to read as a different family
   of control from the .btn it sits above. A px value is right here where a rem
   value is not, because the scale is about the shape of the corner rather than
   about the size of the text inside it: a reader who enlarges their root font
   wants a bigger button, not a rounder one. */
.skip:focus{left:.5rem;top:.5rem;position:fixed;background:var(--cyan);color:var(--navy);
padding:.6rem 1rem;z-index:99;border-radius:12px;font-weight:600}
/* --- the shell, matching the siblings line for line --- */
header.site{border-bottom:1px solid var(--hair);padding:1rem 0;margin-bottom:2.6rem;
padding-top:calc(1rem + env(safe-area-inset-top))}
/* flex-wrap, and it matters: without it the nav is squeezed into whatever the
   wordmark leaves and wraps inside itself into two ragged lines. With it the
   nav drops to its own full-width row on a phone and sits on one line, which
   is what the siblings do. */
header.site .wrap{display:flex;align-items:baseline;gap:1.6rem;flex-wrap:wrap}
.wm{display:flex;align-items:center;flex:none}
.wm svg{display:block;height:1.6rem;width:auto}
nav.top{display:flex;gap:1.4rem;font-size:.95rem;font-weight:500;flex-wrap:wrap;
margin-left:auto}
/* --ink at .82, not --greytx: the model site's header nav, matched. Seen next
   to a physics tab the dimmer grey read as a disabled bar rather than a
   quieter one. */
nav.top a{color:var(--ink);opacity:.82;text-decoration:none}
/* Hover is cyan, not the subject accent, and the difference is not a detail.
   The brand guide gives the subject accent exactly two jobs on a page: the dot
   in the wordmark, and the nav item you are currently on. Everything else that
   responds to a pointer is cyan, which is the one interactive colour shared by
   all three libraries. Biology had the accent on hover as well, so under a
   coral subject accent every one of Revise / Practise / Boards / Search turned
   coral under the mouse, which is the exact signal that is supposed to mean
   "this is the page you are reading". Two states painted the same colour is
   two states a reader cannot tell apart. The accent still belongs on the
   current item, because that is the state the guide reserves it for, and
   brand.SHELL_CSS is where that rule lives for all three subjects -- this
   file used to carry a local copy of it, which is exactly the kind of
   duplication that let maths ship the same rule without its opacity reset. */
nav.top a:hover{color:var(--cyan);opacity:1}
/* Once the nav has wrapped to its own row, margin-left:auto is still pushing
   it right, so it sat indented under a wordmark it should be squared up with.
   The siblings spread it across the row instead. */
@media (max-width:680px){header.site .wrap{row-gap:.4rem}
nav.top{width:100%;margin-left:0;justify-content:space-between;gap:.4rem .9rem;
font-size:.9rem}}
.wrap{max-width:64rem;margin:0 auto;padding:0 1.2rem;width:100%}
main{flex:1 0 auto;width:100%}
main .wrap{max-width:var(--wpanel)}
h1{font-weight:700;font-size:clamp(2.05rem,5.4vw,2.9rem);line-height:1.14;
letter-spacing:-.012em;text-wrap:balance;margin:.1rem 0 .55rem}
/* The section dot, and the type scale the other two libraries use.
   Biology set its headings a step smaller than physics and maths and had
   no dot at all, so a reader moving between libraries met a different
   typographic voice in each and lost the one mark that says "a new
   section starts here". The dot is a fixed brand element rather than a
   flourish, which is why it is cyan in all three: the guide gives a
   subject its colour in exactly two places, and this is not one of them.
   display:flex is what the dot needs to sit on the baseline beside the
   words rather than above them. */
h2{font-weight:700;font-size:1.42rem;line-height:1.3;margin:2.9rem 0 .9rem;display:flex;align-items:center;gap:.6rem;text-wrap:balance}
h2::before{content:"";width:.48rem;height:.48rem;border-radius:50%;background:var(--cyan);flex:none}
/* Where the dot must not appear. A card, a checklist unit, a key-idea
   block and a reference group all use an H2 for the level rather than for
   the size, because a page that goes H1 straight to H3 leaves a hole in
   the outline. The dot marks a new section of the page, and a card is not
   one, so those headings keep the level and lose the mark. Same list as
   physics and maths, including classes biology has not built yet: a rule
   that turns something off costs nothing when there is nothing to turn
   off, and it means a component arriving later cannot arrive wrong. */
.card h2::before,.rpcard h2::before,.cklesson h2::before,.ki h2::before,.eqgrp h2::before,footer.site h2::before{content:none;display:none}
.card h2,.rpcard h2,.cklesson h2,.ki h2,.eqgrp h2{display:block}
h3{font-weight:600;font-size:1.06rem;line-height:1.35;margin:1.9rem 0 .5rem}
p{max-width:var(--wtext)}
.lede{color:var(--greytx);font-weight:500;font-size:1.17rem;line-height:1.6;
margin-bottom:1.3rem;text-wrap:pretty}
.crumbs{font-size:.85rem;font-weight:500;color:var(--greytx);margin:0 0 1.15rem;
letter-spacing:.01em}
.crumbs a{color:var(--greytx);text-decoration:none}
.crumbs a:hover{color:var(--cyan);text-decoration:underline}
/* --- the callouts ---
 *
 * A word about the numbers, because they are not free choices. The brand guide
 * publishes one radius scale for all three libraries, and it is banded by what
 * a thing is rather than by how big it happens to be: inputs and ordinary
 * buttons at 10 to 12px, compact notices and strips at 14 to 16px, cards and
 * panels at 18 to 20px, and nothing above 22px, which is reserved for the
 * large interactive cards a reader actually clicks through.
 *
 * This library drew every one of those components a step tighter than its
 * siblings -- panels at 16 where physics uses 20, the lesson card at 14 where
 * physics uses 20 -- which is invisible on any one page and unmistakable when
 * a reader moves between subjects, because the same component changes shape
 * under them for no reason they can name. The values below are the shared
 * ones. Where a component is genuinely a compact notice rather than a panel
 * (.lie and .rule, which are a few lines each and sit inside the prose column)
 * it keeps 14px, because that is what the band says, not because it was left
 * alone. */
.lie{background:rgba(239,71,111,.07);border:1px solid rgba(239,71,111,.28);
border-radius:14px;padding:.95rem 1.15rem;margin:1.6rem 0;max-width:var(--wpanel)}
.lieh,.exh,.caph,.priorh,.qh{font-size:.72rem;text-transform:uppercase;
letter-spacing:.1em;color:var(--greytx);font-weight:600;margin:0 0 .4rem}
/* The misconception label, laid out to match physics's .pl exactly: a row with
   the cross first and the words after it, at the same size, weight and letter
   spacing the siblings use, so the same idea looks like the same thing in all
   three libraries. The icon has to be flex:none or it is squeezed to nothing
   the moment the label wraps on a narrow phone, which is precisely where the
   reader most needs the glyph the guide asks for. */
.lieh{color:var(--coral);display:flex;align-items:center;gap:.6rem;
font-size:.73rem;font-weight:700;letter-spacing:.16em;margin-bottom:.6rem}
.pi{width:1.05rem;height:1.05rem;flex:none}
.goals,.exam{padding-left:1.15rem;max-width:var(--wtext)}
.goals li,.exam li{margin:.42rem 0}
/* In this lesson: a strip, at the strip radius, deliberately quieter than the
   panels around it. It is a map rather than teaching, so it is set at .95rem
   on the card surface with the numbers in grey, and it is the one list on a
   lesson page whose items are close together on purpose: a contents that
   takes half a screen has stopped being a shortcut. The links still get a
   .35rem gap, which keeps a touch target usable without spacing the list out
   into a menu. */
nav.toc{background:var(--card);border:1px solid var(--edge);border-radius:14px;
padding:.75rem 1rem .85rem;margin:1.5rem 0;max-width:var(--wpanel)}
.toch{font-size:.72rem;text-transform:uppercase;letter-spacing:.1em;
color:var(--greytx);font-weight:600;margin:0 0 .45rem}
nav.toc ol{margin:0;padding-left:1.35rem;font-size:.95rem}
nav.toc li{margin:.35rem 0;color:var(--greytx)}
nav.toc a{color:var(--ink);text-decoration:none}
nav.toc a:hover{color:var(--cyan);text-decoration:underline;text-underline-offset:3px}
/* The same spacing as physics and maths, which agreed with each other and
   not with this file. A figure is centred rather than left-aligned for the
   same reason there: on a wide screen a figure narrower than the column
   sitting hard left reads as a mistake rather than as a choice. */
figure.fig{margin:2.3rem auto;max-width:var(--wfig)}
/* The figure surface is a panel: it holds a drawing, a border and a caption
   rule, and it is the largest single object on most lesson pages. 20px. */
.figbox{background:rgba(255,255,255,.02);border:1px solid var(--hair);
border-radius:20px;padding:.7rem}
.figbox svg{display:block;width:100%;height:auto}
/* A figure whose smallest label would project below 9 CSS px on a phone keeps
   a build-computed minimum artwork width (--figmin) and scrolls sideways
   instead of shrinking its labels past reading size. fig.js makes the viewport
   a named, keyboard-focusable region only while it actually overflows, so it
   is never a tab stop that goes nowhere. The overflow moved here from .figbox:
   the panel is the frame, the scroller is the thing that scrolls, and they
   have to be two elements because the script rewrites role and aria-label on
   the scroller and the panel is where the figure's own name lives. */
.figscroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.figscroll svg{min-width:var(--figmin,0)}
.figscroll:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}
/* The caption row is a flex row so the expand control can sit at the end of
   it: below the artwork, never over it, which is the rule the siblings follow
   because a control floating on a diagram covers the part of the diagram it is
   floating on. */
figcaption{display:flex;gap:.7rem;align-items:baseline;
border-top:1px solid var(--hair);margin-top:.7rem;padding-top:.55rem;
color:var(--greytx);font-size:.9rem;line-height:1.55}
/* 2.75rem square is 44px at the 16px root: the smallest control a thumb can
   be asked to hit. It is drawn quiet and comes up to full strength on hover,
   because it is an offer rather than an instruction. */
.figxbtn{flex:none;margin-left:auto;align-self:center;width:2.75rem;height:2.75rem;
border-radius:12px;border:1px solid var(--edge);background:var(--bg);
color:var(--greytx);cursor:pointer;display:flex;align-items:center;
justify-content:center;padding:0;opacity:.85}
.figxbtn:hover{color:var(--cyan);border-color:var(--cyan);opacity:1}
.figxbtn svg{width:1.05rem;height:1.05rem}
dialog.figdlg{background:var(--bg);border:1px solid var(--edge);border-radius:20px;
padding:0;width:min(96vw,1150px);max-height:92vh;margin:auto;color:var(--ink)}
dialog.figdlg[open]{display:flex;flex-direction:column}
dialog.figdlg::backdrop{background:rgba(4,10,17,.82)}
.figdlgbar{display:flex;align-items:center;gap:1rem;justify-content:space-between;
padding:.55rem .55rem .55rem .95rem;border-bottom:1px solid var(--hair)}
.figdlgbar p{margin:0;font-size:.85rem;color:var(--greytx);line-height:1.35}
.figdlgclose{flex:none;border:1px solid var(--edge);background:none;color:var(--ink);
font:inherit;font-size:.85rem;border-radius:12px;padding:.35rem .8rem;cursor:pointer}
.figdlgclose:hover{border-color:var(--cyan);color:var(--cyan)}
.figdlgpan{overflow:auto;flex:1;min-height:0;padding:.9rem;
-webkit-overflow-scrolling:touch}
.figdlgpan svg{width:900px;max-width:none;display:block;margin:0 auto}
@media print{.figxbtn,dialog.figdlg{display:none}}
/* The definitions list is a panel on the card surface, the same object as .ex
   and .check with a different thing inside it, so it takes the panel radius. */
dl.defs{background:var(--card);border:1px solid var(--edge);border-radius:20px;
padding:1rem 1.2rem;margin:1.6rem 0;max-width:var(--wpanel)}
dl.defs dt{font-weight:600;font-size:.97rem;margin-top:.85rem;color:var(--cyan)}
dl.defs dt:first-child{margin-top:0}
dl.defs dd{margin:.2rem 0 0;color:var(--ink)}
table{border-collapse:collapse;width:100%;font-size:.94rem;margin:.4rem 0}
th,td{padding:.5rem .65rem;border-bottom:1px solid var(--hair);text-align:left;
vertical-align:top}
th{font-size:.74rem;text-transform:uppercase;letter-spacing:.08em;color:var(--greytx);
font-weight:600}
.scroll{overflow-x:auto;margin:1.4rem 0;max-width:var(--wpanel)}
/* A displayed relationship is a strip, not an input: one line of text on the
   card surface, the same object as .priors below it. Both sat at 12px, which
   is the input radius, and read as something you could type into. 14px is the
   bottom of the strip band and is what they are. */
p.eq{background:var(--card);border:1px solid var(--edge);border-radius:14px;
padding:.75rem 1rem;font-size:1.04rem;margin:1.3rem 0;max-width:var(--wpanel)}
.eqnote{display:block;font-size:.85rem;color:var(--greytx);margin-top:.35rem}
/* The five panels of a lesson: worked reasoning, the guided attempt, the
   self-check, a practical capability and an exam question. Panels, at the
   panel radius the siblings draw them at. */
.ex,.exs,.check,.cap,.q{background:var(--card);border:1px solid var(--edge);
border-radius:20px;padding:1rem 1.2rem;margin:1.6rem 0;max-width:var(--wpanel)}
.exs{background:rgba(255,183,3,.05);border-color:rgba(255,183,3,.24)}
.task{font-weight:600}
details{margin-top:.7rem}
summary{cursor:pointer;display:inline-flex;align-items:center;gap:.5rem;font-weight:500;
color:var(--cyan);border:1px solid rgba(56,182,255,.45);border-radius:11px;
padding:.45rem .95rem;font-size:.9rem;list-style:none}
summary::-webkit-details-marker{display:none}
summary::after{content:"";width:7px;height:7px;border-right:2px solid currentColor;
border-bottom:2px solid currentColor;transform:rotate(45deg) translateY(-2px);
transition:transform .15s}
details[open] summary::after{transform:rotate(-135deg) translateY(-2px)}
/* An optional section: its heading is the summary, so the h2 keeps its place
   in the page and the contents list while the body stays folded. The pill
   styling the generic summary carries would swallow an h2, so this variant
   is unboxed and lets the heading look like every other heading. */
.optsec>summary{display:flex;align-items:baseline;gap:.7rem;border:0;
padding:0;color:inherit;font-size:inherit;font-weight:inherit;border-radius:0}
.optsec>summary h2{margin:2.2rem 0 .9rem;display:inline}
.optsec>summary .optnote{color:var(--greytx);font-size:.8rem;
text-transform:uppercase;letter-spacing:.04em}
.optsec>summary::after{align-self:center}
.rule{border:1px solid rgba(56,182,255,.28);background:rgba(56,182,255,.05);
border-radius:14px;padding:.9rem 1.15rem;margin:2rem 0;max-width:var(--wpanel)}
.rule ul{margin:.35rem 0;padding-left:1.15rem}
.rule li{margin:.35rem 0}
.meta{color:var(--greytx);font-size:.9rem}
/* The prerequisites line is a strip: one row of links above the lesson. 14px,
   the same as p.eq, for the same reason given there. */
.priors{font-size:.92rem;color:var(--greytx);background:var(--card);
border:1px solid var(--edge);border-radius:14px;padding:.6rem .9rem;margin:1.2rem 0;
max-width:var(--wpanel)}
.priorh{display:inline;margin-right:.5rem}
.cap h2{font-size:1.06rem;margin:.1rem 0 .5rem;line-height:1.3}
.cap ul{margin:.25rem 0 0;padding-left:1.2rem}.cap ul li{margin:.32rem 0}
.caph{margin:1.1rem 0 .15rem}.caph:first-of-type{margin-top:.7rem}
.pid{font-size:.76rem;letter-spacing:.08em;color:var(--greytx);font-weight:600}
/* The closed capability. The row is shaped like details.ub, which is the
   disclosure this library already uses on the checklist and the definitions
   pages: the whole row is the target, it is at least 44px tall, and the state
   is a chevron that turns. What it is not shaped like is the cyan pill the
   generic `summary` rule draws, and the overrides below are there to undo that
   rule rather than to invent a third look: a pill is right for "Mark scheme",
   which is one small reveal inside a paragraph of prose, and wrong for a
   heading that owns everything under it.
   list-style:none plus the WebKit marker rule, both, because Safari still
   needs the second one. */
details.cap>summary{display:flex;align-items:center;gap:.9rem;cursor:pointer;
list-style:none;border:0;background:none;padding:0;min-height:44px;
box-sizing:border-box;color:var(--ink);font-weight:400;font-size:inherit}
details.cap>summary::-webkit-details-marker{display:none}
details.cap>summary::after{content:'';flex:none;width:.55rem;height:.55rem;
border-right:2px solid var(--greytx);border-bottom:2px solid var(--greytx);
transform:rotate(45deg);transition:transform .18s ease;margin-right:.2rem}
details.cap[open]>summary::after{transform:rotate(-135deg)}
.capsh{flex:1;min-width:0}
details.cap>summary:hover h2,details.cap>summary:focus-visible h2{color:var(--cyan)}
details.cap h2{margin:.15rem 0 .2rem}
.capsum{display:block;color:var(--greytx);font-size:.92rem;line-height:1.5}
.qh{display:flex;justify-content:space-between;gap:1rem;margin-bottom:.5rem}
.qm{color:var(--cyan);font-weight:600}
ol.scheme{margin:.55rem 0 0;padding-left:1.35rem;font-size:.95rem}
ol.scheme li{margin:.38rem 0}
.mcode{font-size:.74rem;font-weight:700;color:var(--cyan);margin-right:.4rem;
letter-spacing:.04em}
.units li{margin:.5rem 0}
.lessons{list-style:none;padding:0;display:flex;flex-direction:column;gap:.55rem;
max-width:var(--wpanel)}
.lessons li{margin:0;padding:0}
/* The lesson card on a unit page is the same object as a.card below it and as
   physics's .card: a bordered surface on the card ground that lifts a pixel
   under the pointer and takes you somewhere. It was drawn at 14px, so a unit
   listing and the front door disagreed with each other on one page's scroll.
   20px, which is what both siblings draw the lesson card at. */
.lessons a{display:block;border:1px solid var(--edge);background:var(--card);
border-radius:20px;padding:.75rem .95rem;text-decoration:none;font-weight:500;
color:var(--ink);transition:border-color .18s,transform .18s}
.lessons a:hover{border-color:rgba(56,182,255,.5);transform:translateY(-1px)}
/* The end of a lesson, ported from physics rule for rule.
 *
 * This library ended a lesson with a line of small grey text: an arrow, the
 * previous title, a middle dot, the next title, an arrow. It is the same
 * information the siblings carry and it looked like a footnote, so the single
 * most-used link on a lesson page was the least visible thing on it and had a
 * tap target the height of one line of 0.9rem text, which is under the 44px a
 * thumb needs. The siblings end on a pair of cards with the word PREVIOUS or
 * NEXT above the title, and a reader moving between subjects should not have
 * to learn where the next lesson is twice.
 *
 * .pn is the row, .next is each card, .pnl is the small label above the title.
 * The arrow is mirrored rather than drawn twice, which is what .rev does. */
.next{display:inline-flex;align-items:center;gap:.6rem;border:1px solid var(--edge);
border-radius:14px;padding:.7rem 1.2rem;color:var(--ink);font-weight:500;
text-decoration:none;
transition:border-color .18s,transform .18s cubic-bezier(.2,.9,.3,1.25)}
.next:hover{border-color:var(--cyan);text-decoration:none;transform:translateY(-1px)}
.next svg{width:1rem;height:1rem;flex:none}
.pn{display:flex;gap:.9rem;justify-content:space-between;flex-wrap:wrap;
margin:2.4rem auto 0;max-width:var(--wpanel)}
.pn .next{max-width:100%}
.pn .rev svg{transform:scaleX(-1)}
.pn .pnl{font-size:.68rem;font-weight:700;letter-spacing:.15em;color:var(--greytx);
display:block}
/* The hero, the action row and the cards: the front-door furniture both
   siblings use. This library's front door was a paragraph and a bulleted list
   of twenty-one units -- accurate, and the only one of the three that did not
   look like a front door. */
.hero{text-align:center;padding:2.4rem 0 1rem;max-width:var(--wpanel);margin:0 auto}
.bigwm{margin:0 0 .1rem;display:flex;justify-content:center}
.bigwm svg{height:3.1rem;width:auto}
h1.tag{color:var(--greytx);font-weight:500;font-size:1.14rem;margin:.5rem 0 1.2rem;
letter-spacing:0;text-wrap:pretty}
.hero p{margin-left:auto;margin-right:auto}
.hero .links{display:flex;gap:.85rem;justify-content:center;flex-wrap:wrap;
margin:1.6rem 0 .4rem}
.btn{background:transparent;border:1px solid var(--edge);border-radius:12px;
padding:.58rem 1.15rem;font-weight:500;color:var(--ink);text-decoration:none;
transition:border-color .18s,transform .18s cubic-bezier(.2,.9,.3,1.25);
display:inline-block}
.btn:hover{border-color:rgba(56,182,255,.55);transform:translateY(-1px)}
.btn.primary{border-color:var(--cyan);color:var(--cyan)}
/* The subject cards, the shape the front doors of the other two use. */
.cards{display:grid;gap:.95rem;grid-template-columns:1fr;margin:1.5rem 0;
max-width:var(--wpanel)}
@media (min-width:44rem){.cards{grid-template-columns:1fr 1fr}}
.wbblock{margin:2.4rem 0 0;padding:1.4rem 1.5rem;border:1px solid var(--edge);
 border-radius:20px;background:var(--card)}
/* A card inside a panel must not repaint the panel's own surface. Both carry
   --card, a translucent white over the navy, so a workbook card sitting in a
   workbook block stacked two tints and lifted the ground under it from the
   navy the palette assumes to a lighter grey. Muted text on that doubled
   surface measures 4.49:1, which fails WCAG AA for body text by a hundredth;
   on the single surface it is 4.96:1 and passes. Fixing the nesting rather
   than the colour keeps both approved tokens exactly as the brand guide sets
   them, and follows the guide's own rule that a surface inside a surface is
   told apart by its border rather than by a second fill. The siblings carry
   the same rule for the same reason. */
.wbblock .card{background:transparent}
.wbblock .gl{font-size:.72rem;letter-spacing:.14em;color:var(--cyan);font-weight:600;
 margin:0 0 .5rem}
.wbblock>p{margin:0 0 1rem;color:var(--greytx)}
.wbblock .cards{grid-template-columns:repeat(auto-fit,minmax(210px,1fr));margin:0}
.card.wb h2{display:flex;align-items:center;gap:.4rem;font-size:1rem;margin:0 0 .25rem}
.card.wb h2 .pi{width:1rem;height:1rem;flex:none}
/* .card, not a.card. The rule was written when every card on the library was
   a link, and the exam-boards page now needs the same surface for a card that
   is a statement rather than a destination: it tells you where a route stands
   and what to read next, and there is no single page it could sensibly send
   you to. Physics writes the base rule the same way, on .card, and keeps the
   lift and the border change on a.card:hover, which is right: a surface that
   rises under the pointer and then does nothing when clicked is a lie about
   what it is. */
.card{border:1px solid var(--edge);background:var(--card);border-radius:20px;
padding:1.05rem 1.15rem;color:var(--ink);display:block;text-decoration:none;
transition:transform .18s cubic-bezier(.2,.9,.3,1.25),border-color .18s}
a.card:hover{transform:translateY(-2px);border-color:rgba(56,182,255,.5)}
.card h2{font-size:1.1rem;margin:0 0 .35rem}
.card p{margin:.5rem 0 0}
.card p:first-of-type{margin-top:.15rem}
footer.site{flex-shrink:0;margin-top:3.4rem;border-top:1px solid var(--hair);
padding:1.5rem 0 2.3rem;color:var(--greytx);font-size:.87rem}
footer.site .wrap{display:flex;flex-direction:column;gap:.7rem}
footer.site a{color:var(--greytx)}
footer.site a:hover{color:var(--cyan)}
/* The flag control's own rules are in brand.FLAG_CSS, which this sheet
   concatenates further down. Three local copies used to sit here and were
   dead the whole time -- the shared block came later in the file and won on
   source order -- so the local padding:0 and missing min-height never
   actually shrank the button below its 44px target. Removed rather than
   corrected: a rule that has no effect is worse than a wrong one, because
   the next reader budgets time to understand it. */
/* --- the installed app --- */
/* Hidden in a browser tab and shown once the reader has installed, which is
   the arrangement both siblings use: on the web the header nav and the footer
   carry navigation, and in a standalone window a bottom bar does.

   Almost none of that layer is written here. client.APP_CSS, concatenated
   below, is the ported copy the siblings share and it carries the whole tab
   bar: the fixed bar, its blur, its icons, its press state, the standalone
   heading sizes. This block used to carry a second, older copy of all of it,
   which the shared one then overrode declaration for declaration -- so the
   only thing the duplicate decided was that a future edit to one of them
   would take effect on some rules and not others. One of them had already
   drifted: the local .lede was .99rem against the shared .98rem, and the
   shared one silently won.

   What is left here is the three rules the shared layer genuinely does not
   have, because they are about biology's own markup rather than the tab bar:
   its footer groups need hiding, and it marks the current tab with
   aria-current where the shared copy expects the .on class its own script
   adds. Its breadcrumb used to be a third entry on this list, called .crumb
   against the siblings' .crumbs; it is .crumbs now, so the shared layer hides
   it along with theirs. */
@media (display-mode: standalone){
footer.site .fgroups{display:none}
.apptabs a[aria-current=page]{color:var(--cyan)}
}
/* The offline notice the worker raises when a page is served from the cache
   and the network is gone. Hidden until something sets the attribute. */
.offpill{display:none;margin-left:auto;font-size:.7rem;font-weight:600;
letter-spacing:.06em;text-transform:uppercase;color:var(--amber);
border:1px solid rgba(255,183,3,.4);border-radius:999px;padding:.1rem .55rem}
body[data-offline] .offpill{display:inline-block}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
/* The print block, whose core is brand.PRINT_CSS and which biology did not
   have. It set the page white and the body text black and stopped there,
   which left every token at its screen value -- so --ink stayed at #F5F5F5
   and anything colouring itself from a token, every link included, printed
   white on white. The hide list below is biology's own: it is the only
   subject with a tab bar and a report row to suppress. */
@media print{
:root{--bg:#ffffff;--ink:#15222e;--cyan:#0b6fae;--amber:#8a6100;--coral:#b3264e;--grey:#5a6570;--greytx:#5a6570;--card:#ffffff;--edge:#c9d1d8;--hair:#dfe5ea}
body{background:#fff;font-size:11pt;line-height:1.55}
a{color:inherit;text-decoration:none}
figure.fig,.panel,.eqs,.goals{break-inside:avoid;page-break-inside:avoid}
details{display:block}details summary{display:none}details>*{display:block}
.card{box-shadow:none}
body{padding-bottom:0}
header.site,footer.site,.flagrow,.apptabs{display:none}}

.ckbar{display:flex;gap:.55rem;flex-wrap:wrap;margin:.2rem 0 1rem}.ckbar button{font:inherit;font-size:.82rem;padding:.4rem .8rem;border:1px solid var(--edge);border-radius:12px;background:var(--card);color:var(--ink);cursor:pointer}.ckbar button:hover{border-color:var(--cyan)}.ckbar button[aria-pressed=true]{border-color:var(--cyan);color:var(--cyan)}.cklegend{font-size:.8rem;color:var(--greytx);margin:.1rem 0 1.5rem}.cklegend span{white-space:nowrap;margin-right:1rem;line-height:2}.cklegend i{display:inline-flex;align-items:center;justify-content:center;font-style:normal;font-weight:700;font-size:.5rem;color:#0D1B2A;width:.72rem;height:.72rem;border-radius:50%;margin-right:.32rem;vertical-align:middle;box-sizing:border-box}.cklist{list-style:none;padding:0;margin:.2rem 0}li.ck{display:flex;gap:.65rem;align-items:flex-start;padding:.28rem 0}li.ck.hide{display:none}.ckdot{flex:0 0 auto;width:1.3rem;height:1.3rem;margin-top:.1rem;border-radius:50%;border:2px solid var(--grey);background:transparent;cursor:pointer;padding:0;position:relative;transition:background .12s,border-color .12s}.ckdot::before{content:'';position:absolute;inset:-12px}.ckdot::after{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:.76rem;font-weight:700;color:#0D1B2A;line-height:1}.ckdot:hover{border-color:var(--cyan)}li.ck[data-state="1"] .ckdot{background:var(--coral);border-color:var(--coral)}li.ck[data-state="1"] .ckdot::after{content:"!"}li.ck[data-state="2"] .ckdot{background:var(--amber);border-color:var(--amber)}li.ck[data-state="2"] .ckdot::after{content:"~"}li.ck[data-state="3"] .ckdot{background:#2ea043;border-color:#2ea043}li.ck[data-state="3"] .ckdot::after{content:"\2713"}.cktext{flex:1;line-height:1.45}.cktally{display:block;font-size:.8rem;color:var(--greytx);font-weight:400;letter-spacing:0;margin-top:.2rem}.cklesson{margin:0 0 1.15rem}.cklesson h3,.cklesson h2{margin:.1rem 0;font-size:1.02rem}.ckspec{font-size:.76rem;color:var(--greytx);font-weight:400;margin-left:.15rem}.ckstrip{margin-top:2.2rem;padding-top:1.3rem;border-top:1px solid var(--hair)}.ckstrip .cknote{font-size:.85rem;margin-top:.75rem}
.gdef{margin:0 0 .85rem}.gdef dt{font-weight:700;margin:.7rem 0 .1rem}.gdef dd{margin:0;line-height:1.5}.glink{color:var(--greytx);font-size:.88rem}.gl-let{font-size:1.5rem;margin:1.7rem 0 .3rem;color:var(--cyan);border-bottom:1px solid var(--hair);padding-bottom:.15rem}
.qr dl{margin:0 0 .5rem}.qr dt{font-weight:700;margin:1.15rem 0 .15rem;color:var(--ink)}.qr dd{margin:0;line-height:1.5}.qr dd .eg{display:block;color:var(--greytx);font-size:.9rem;margin-top:.15rem}.ki{margin:0 0 1rem}.ki h3{margin:.1rem 0 .25rem;font-size:1.0rem}.ki ul{list-style:none;padding:0;margin:0}.ki li{padding:.1rem 0 .1rem .9rem;border-left:2px solid var(--edge);margin:.32rem 0;line-height:1.45}.ub{border-bottom:1px solid var(--edge)}.ub>summary::-webkit-details-marker{display:none}.ub>summary::after{content:'';margin-left:auto;flex:none;width:.5rem;height:.5rem;border-right:2px solid var(--greytx);border-bottom:2px solid var(--greytx);transform:rotate(45deg);transition:transform .18s ease;align-self:center}.ub[open]>summary::after{transform:rotate(-135deg)}.ub>summary:hover .ubt,.ub>summary:focus-visible .ubt{color:var(--cyan)}.ubt{font-weight:600;color:var(--ink)}.ubm{color:var(--greytx);font-size:.86rem}.ubn{color:var(--greytx);font-size:.74rem;font-weight:700;letter-spacing:.1em;border:1px solid var(--edge);border-radius:6px;padding:.06rem .48rem;flex:none;white-space:nowrap}.ubb{padding:.1rem 0 1.1rem}.fltbar{position:sticky;top:0;z-index:5;background:var(--bg);padding:.7rem 0 .5rem;margin:0 0 .4rem}.fltcount{display:flex;gap:.6rem;justify-content:space-between;margin:.35rem .1rem 0;font-size:.78rem;color:var(--greytx)}.fcgo{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem .9rem;margin:.7rem 0 .2rem}.fcstart{font-weight:700;font-size:1rem;padding:.62rem 1.5rem;border-radius:999px;background:var(--cyan);color:var(--navy);border:0;cursor:pointer;min-height:44px}.fcstart:disabled{background:none;color:var(--greytx);border:1px solid var(--edge);cursor:default}.fcstart:hover{filter:brightness(1.08)}.fclink2{background:none;border:0;color:var(--greytx);font-size:.9rem;cursor:pointer;padding:.5rem .1rem;text-decoration:underline;text-underline-offset:3px;min-height:44px}.fclink2:hover,.fclink2:focus-visible{color:var(--cyan)}.fcman{margin:.5rem 0 0}.fcman>summary{cursor:pointer;color:var(--greytx);font-size:.84rem;padding:.45rem .1rem;min-height:44px;display:flex;align-items:center}.fcman>summary:hover{color:var(--cyan)}.azjump a:hover,.azjump a:focus-visible{color:var(--cyan)}@media print{.fltbar{display:none}.ub>summary::after{display:none}}.ki h2{margin:.1rem 0 .25rem;font-size:1.0rem}.ki h2{display:block;line-height:1.3;gap:0;letter-spacing:normal}.ki h2::before{content:none;display:none}.ub>summary{display:flex;align-items:baseline;flex-wrap:wrap;gap:.2rem .6rem;cursor:pointer;padding:.85rem .2rem;list-style:none;min-height:44px;box-sizing:border-box}
.fcbar{margin:.2rem 0 1.2rem}.fcbar[hidden]{display:none}.fcrow{display:flex;gap:.55rem;flex-wrap:wrap}.fcscope{display:flex;gap:.9rem;flex-wrap:wrap;margin:0 0 .65rem}.fcbar button,.fcgrade button,.fcnav button,.fcpr{font:inherit;font-size:.82rem;padding:.4rem .8rem;border:1px solid var(--edge);border-radius:12px;background:var(--card);color:var(--ink);cursor:pointer}.fcbar button:hover,.fcgrade button:hover,.fcnav button:hover,.fcpr:hover{border-color:var(--cyan)}@media (max-width:560px){.fcrow{display:grid;grid-template-columns:1fr 1fr;gap:.45rem}.fcrow button{width:100%}}.fccard{display:flex;flex-direction:column;width:100%;max-width:660px;margin:.4rem auto 1rem;background:var(--card);border:2px solid rgba(56,182,255,.55);border-radius:22px;padding:1.5rem 1.7rem 1.2rem;min-height:15rem;cursor:pointer;text-align:left;color:var(--ink);font:inherit;transition:transform .14s ease}.fccard.turn{transform:rotateY(90deg)}.fccard:focus-visible{outline:2px solid var(--cyan);outline-offset:3px}.fctype{font-size:.72rem;font-weight:700;letter-spacing:.14em;color:var(--cyan);margin:0 0 .7rem}.fctopic{font-size:.78rem;color:var(--greytx);margin:0 0 .25rem}.fcq{font-size:1.12rem;line-height:1.55;margin:.2rem 0}.fccard .r1,.fccard .r2{font-weight:700;font-size:1.05rem;line-height:1.5;margin:.5rem 0}.fccard .r2{color:var(--cyan)}.fcfoot{display:flex;justify-content:space-between;align-items:center;margin-top:auto;border-top:1px solid var(--hair);padding-top:.7rem;font-size:.8rem;color:var(--greytx)}.fcprog{font-size:.85rem;color:var(--greytx);max-width:660px;margin:.4rem auto}.fcgrade{display:flex;gap:.55rem;max-width:660px;margin:.4rem auto 1rem}.fcgrade button{flex:1;text-align:center}.fcgrade button.g1{border-color:var(--coral)}.fcgrade button.g2{border-color:var(--amber)}.fcgrade button.g3{border-color:var(--cyan)}.fcnav{display:flex;gap:.55rem;max-width:660px;margin:.2rem auto 1.2rem}.fcunit{margin-top:2.4rem}.fcunit h2 .fcpr{margin-left:.7rem;vertical-align:middle}.fccard .eqs{margin:.9rem auto}.fccard .eqs .eq{font-size:clamp(1rem,3.4vw,1.25rem)}@media print{.fcbar,#fcplayer{display:none}}.fcscope label{display:flex;align-items:center;gap:.45rem;font-size:.82rem;color:var(--greytx);flex-wrap:wrap;max-width:100%}.fcscope select{font:inherit;font-size:.82rem;padding:.35rem .5rem;max-width:100%;border:1px solid var(--edge);border-radius:.45rem;background:var(--card);color:var(--ink)}.fcscope select:hover{border-color:var(--cyan)}
.tqlist{list-style:none;padding:0;margin:1.4rem 0}.tqq{border-top:1px solid var(--hair);padding:1rem 0}.tqq:last-child{border-bottom:1px solid var(--hair)}.tqmeta{font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--greytx);margin:0 0 .35rem}.tqtext{margin:0}.tqa{margin:.6rem 0 0}.tqa summary{cursor:pointer;font-size:.85rem;color:var(--cyan);padding:.35rem 0;min-height:32px}.tqa>div{border-left:2px solid var(--edge);padding:.1rem 0 .1rem .8rem;margin:.3rem 0 0;color:var(--greytx);font-size:.94rem}.tqgo{margin:1.6rem 0 .4rem}.qbbar{margin:.2rem 0 1.1rem}.qbbar[hidden]{display:none}.qbscope{display:flex;flex-wrap:wrap;gap:.5rem 1rem;align-items:baseline;font-size:.92rem;color:var(--greytx);margin-bottom:.2rem}.qbscope label{min-width:0}.qbscope select{width:100%}select option{background:var(--navy);color:var(--ink)}@media print{:root{color-scheme:light}}.qbgo{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem .9rem;margin:.7rem 0 .2rem}.qbstart{font-weight:700;font-size:1rem;padding:.62rem 1.5rem;border-radius:999px;background:var(--cyan);color:var(--navy);border:0;cursor:pointer;min-height:44px}.qbstart:hover{filter:brightness(1.08)}.qbstart:disabled{background:none;color:var(--greytx);border:1px solid var(--edge);cursor:default}.qblink{background:none;border:0;color:var(--greytx);font-size:.9rem;cursor:pointer;padding:.5rem .1rem;text-decoration:underline;text-underline-offset:3px;min-height:44px}.qblink:hover,.qblink:focus-visible{color:var(--cyan)}.qbman{margin:.4rem 0 0}.qbman>summary{cursor:pointer;color:var(--greytx);font-size:.84rem;padding:.45rem .1rem;min-height:44px;display:flex;align-items:center}.qbman>summary:hover{color:var(--cyan)}.qbcard{border:2px solid var(--edge);border-radius:20px;background:var(--card);padding:1.15rem 1.2rem 1.3rem;margin:.4rem 0 1rem}.qbmeta{display:flex;flex-wrap:wrap;gap:.45rem;align-items:center;margin:0 0 .7rem}.qbchip{font-size:.68rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--greytx);border:1px solid var(--edge);border-radius:6px;padding:.1rem .5rem}.qbchip.on{color:var(--navy);background:var(--cyan);border-color:var(--cyan)}.qbq{font-size:1.06rem;line-height:1.55;margin:.1rem 0 .9rem}.qbwork{width:100%;box-sizing:border-box;font:inherit;font-size:.95rem;line-height:1.5;min-height:5.5rem;padding:.6rem .7rem;border-radius:12px;background:var(--bg);color:var(--ink);border:1px solid var(--edge);resize:vertical}.qbhint{font-size:.82rem;color:var(--greytx);margin:.35rem 0 .8rem}.qbans{border-top:1px solid var(--edge);margin-top:1rem;padding-top:.9rem}.qbans h3{font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--cyan);margin:0 0 .5rem}.qbans p{line-height:1.6;margin:.3rem 0}.qbgrade{display:flex;flex-wrap:wrap;gap:.5rem;margin:1rem 0 .2rem}.qbgrade button{font:inherit;font-size:.9rem;font-weight:600;padding:.55rem 1rem;border-radius:999px;cursor:pointer;min-height:44px;border:1px solid var(--edge);background:var(--bg);color:var(--ink)}.qbgrade button:hover{border-color:var(--cyan)}.qbg0{border-color:var(--coral)!important;color:var(--coral)!important}.qbg1{border-color:var(--amber)!important;color:var(--amber)!important}.qbg2{border-color:#2ea043!important;color:#2ea043!important}.qbprog{display:flex;justify-content:space-between;gap:.8rem;font-size:.8rem;color:var(--greytx);margin:.2rem .1rem 0}.qbdone{text-align:center;padding:1.6rem 1rem}.qbdone .big{font-size:1.5rem;font-weight:700;color:var(--ink);margin:.2rem 0 .5rem}.qbpaper{border-top:1px solid var(--edge);padding-top:.7rem;font-size:.92rem;color:var(--greytx)}.qbpaperbar{display:flex;justify-content:space-between;align-items:center;gap:.8rem;margin:.2rem 0 .5rem}.qbclock{font-weight:700;font-size:1.1rem;color:var(--ink);font-variant-numeric:tabular-nums}.qbyours{border-top:1px solid var(--edge);margin-top:1rem;padding-top:.9rem}.qbyours h3{font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--greytx);margin:0 0 .5rem}.qbyours p{white-space:pre-wrap;line-height:1.55;margin:.3rem 0;color:var(--ink)}.qbmarks{align-items:center;gap:.4rem}.qbmkl{font-size:.82rem;color:var(--greytx)}.qbmk{min-width:46px;font-variant-numeric:tabular-nums;font-weight:700;padding:.55rem .5rem}.qbbd{margin:1.1rem 0 0;text-align:left}.qbbd>summary{cursor:pointer;color:var(--greytx);font-size:.84rem;padding:.45rem .1rem;min-height:44px;display:flex;align-items:center}.qbbd>summary:hover{color:var(--cyan)}.qbsketch{margin:.7rem 0 .2rem}.qbskh{font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--greytx);margin:0 0 .4rem}.qbcanvas{--skink:var(--cyan);display:block;width:100%;border-radius:12px;background:var(--bg);border:1px solid var(--edge);touch-action:none;cursor:crosshair}.qbcanvas[data-ro]{cursor:default}.qbsktools{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem .8rem;margin-top:.1rem}@media print{.qbsktools{display:none}.qbbar,.qbgrade,.qbwork{display:none}}.qbbar select{font:inherit;font-size:.92rem;padding:.3rem .5rem;border-radius:8px;background:var(--card);color:var(--ink);border:1px solid var(--edge);max-width:100%}.qbclock.qblow{color:var(--coral)}
.apptabs{display:none}a.searchtop{display:none}@media (display-mode: standalone){nav.top{display:none}a.searchtop{display:flex;align-items:center;color:var(--ink);-webkit-tap-highlight-color:transparent}body{padding-bottom:calc(72px + env(safe-area-inset-bottom))}.apptabs{display:flex;position:fixed;bottom:0;left:0;right:0;z-index:60;background:var(--bg);border-top:1px solid var(--hair);padding-bottom:env(safe-area-inset-bottom)}@supports (backdrop-filter: blur(1px)){.apptabs{background:color-mix(in srgb,var(--bg) 86%,transparent);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}}.apptabs a{flex:1;position:relative;display:flex;flex-direction:column;align-items:center;gap:3px;padding:9px 0 7px;color:var(--greytx);font-size:.6rem;font-weight:500;letter-spacing:.04em;text-decoration:none;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}header.site{padding-top:env(safe-area-inset-top)}.apptabs a svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;transition:transform .12s}.apptabs a.on{color:var(--cyan)}.apptabs a:active svg{transform:scale(.88)}.crumbs{display:none}footer.site{display:none}main h1{font-size:1.7rem}.lede{font-size:.98rem}.topics li.flt{display:flex;align-items:center;justify-content:space-between;gap:.8rem;min-height:50px;border-bottom:1px solid var(--hair);padding:.35rem 0}.lprog{height:4px;background:var(--hair);border-radius:2px;margin:.3rem 0 .55rem;overflow:hidden}.lprog i{display:block;height:100%;width:0;background:var(--cyan);transition:width .25s}.lproglbl{font-size:.72rem;letter-spacing:.06em;color:var(--greytx);text-transform:uppercase;margin:0 0 .9rem}.lstep{display:none}.lstep.on{display:block}.lnav{display:flex;gap:.6rem;margin:1.5rem 0 .6rem}.lnav button{flex:1;font:inherit;font-size:.95rem;padding:.72rem;border-radius:12px;border:1px solid var(--edge);background:var(--card);color:var(--ink);cursor:pointer}.lnav button[data-l-next]{border-color:var(--cyan);font-weight:600}.lnav button:disabled{opacity:.35}.lstep.si-r{animation:stepr .18s ease}.lstep.si-l{animation:stepl .18s ease}.uprog{height:5px;border-radius:3px;background:var(--hair);overflow:hidden;margin:.55rem 0 .25rem}.uprog i{display:block;height:100%;background:var(--cyan);border-radius:3px}.usub{font-size:.72rem;color:var(--greytx)}.donetick{color:var(--cyan);font-weight:700;margin-left:.45rem}.acch{cursor:pointer;-webkit-user-select:none;user-select:none;display:flex;align-items:center;justify-content:space-between;gap:.6rem}.acch::after{content:"";flex:none;width:9px;height:9px;border-right:2px solid var(--greytx);border-bottom:2px solid var(--greytx);transform:rotate(45deg);transition:transform .15s}.acch.acco::after{transform:rotate(225deg)}header.site .wrap{padding-top:.5rem;padding-bottom:.5rem}.fcrow button{flex:1 1 30%;padding:.6rem .5rem}.fcmanage{display:none;margin-top:.55rem}.fcmanage.open{display:flex}.fcmanagetg{font:inherit;font-size:.78rem;background:none;border:0;color:var(--greytx);text-decoration:underline;cursor:pointer;padding:.45rem 0 0;display:block}.fcunit h2 .ckspec{display:none}.exnext{font:inherit;font-size:.85rem;padding:.5rem .95rem;margin:.45rem 0 .15rem;border:1px solid var(--cyan);border-radius:12px;background:var(--card);color:var(--ink);cursor:pointer}.exin{animation:exin .25s ease}}@keyframes exin{from{opacity:0;transform:translateY(6px)}}@keyframes stepr{from{opacity:.25;transform:translateX(26px)}to{opacity:1;transform:none}}@keyframes stepl{from{opacity:.25;transform:translateX(-26px)}to{opacity:1;transform:none}}.hintcard{border:1px solid var(--hair);border-radius:14px;padding:.85rem 1rem;margin:.2rem 0 1rem;font-size:.88rem;color:var(--greytx);display:flex;justify-content:space-between;gap:.8rem;align-items:flex-start}.hintcard button{font:inherit;background:none;border:0;color:var(--cyan);cursor:pointer;padding:0;font-weight:600}.statwrap .big{font-size:1.4rem;font-weight:700;color:var(--ink);margin:.3rem 0}.statbars{display:flex;align-items:flex-end;gap:4px;height:88px;margin:.6rem 0 1rem}.statcol{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;justify-content:flex-end;min-width:0}.statcol i{display:block;width:100%;max-width:22px;border-radius:4px 4px 0 0;background:var(--cyan)}.statcol span{font-size:.56rem;color:var(--greytx);white-space:nowrap}.statrow{display:flex;align-items:center;gap:.7rem;margin:.45rem 0}.statlbl{flex:0 0 9.5rem;font-size:.82rem;color:var(--greytx);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.statprog{flex:1;margin:0}.statn{flex:0 0 3.2rem;text-align:right;font-size:.8rem;color:var(--ink)}@media (max-width:480px){.statlbl{flex-basis:7.2rem;font-size:.74rem}}@media not (prefers-reduced-motion: reduce){@view-transition{navigation:auto}}.tbadge{position:absolute;top:3px;left:50%;margin-left:8px;background:var(--coral);color:#fff;font-style:normal;font-size:.58rem;font-weight:700;line-height:15px;min-width:15px;border-radius:8px;padding:0 4px;text-align:center}.offpill{display:none;align-items:center;font-size:.66rem;letter-spacing:.08em;border:1px solid var(--hair);border-radius:99px;padding:.15rem .55rem;color:var(--greytx)}.offpill.on{display:inline-flex}a.card{transition:transform .12s}a.card:active{transform:scale(.985)}html{-webkit-tap-highlight-color:rgba(56,182,255,.12)}.appdash .big{font-size:1.5rem;font-weight:700;color:var(--ink);margin:.35rem 0}.ckprog{height:7px;border-radius:4px;background:var(--hair);overflow:hidden;margin:.5rem 0}.ckprog i{display:block;height:100%;width:0;border-radius:4px;background:var(--cyan);transition:width .4s}@media (display-mode: standalone){footer.site .fnav{display:none}}
.flagbtn{background:none;border:0;color:var(--greytx);font:inherit;font-size:.78rem;cursor:pointer;padding:.4rem .1rem;text-decoration:underline;text-underline-offset:3px;min-height:44px}.flagbtn:hover,.flagbtn:focus-visible{color:var(--cyan)}.lsec>.flagbtn{display:block;margin:.1rem 0 0}figcaption .flagbtn{font-size:.72rem;min-height:0;padding:.15rem .1rem}.flagrow{margin:.6rem 0 0}.flagdlg{background:var(--bg);background-image:linear-gradient(var(--card),var(--card));color:var(--ink);border:2px solid var(--edge);box-shadow:0 18px 50px rgba(0,0,0,.55);border-radius:18px;padding:1.1rem 1.2rem;max-width:26rem;width:calc(100vw - 2.4rem)}.flagdlg::backdrop{background:rgba(3,8,14,.78)}.flagdlg h2{margin:0 0 .6rem;font-size:1.05rem}.flagcats{display:flex;flex-direction:column;gap:.15rem;margin:0 0 .8rem}.flagcats label{display:flex;gap:.5rem;align-items:baseline;padding:.22rem 0;cursor:pointer}.flagnote{display:block;font-size:.84rem;color:var(--greytx);margin:0 0 .3rem}.flagdlg textarea{width:100%;box-sizing:border-box;font:inherit;font-size:.92rem;min-height:4.2rem;padding:.5rem .6rem;border-radius:10px;background:var(--bg);color:var(--ink);border:1px solid var(--edge);resize:vertical}.flagemail{width:100%;box-sizing:border-box;font:inherit;font-size:.92rem;min-height:44px;padding:.5rem .6rem;border-radius:10px;background:var(--bg);color:var(--ink);border:1px solid var(--edge)}.flagts{margin:.7rem 0 0}.flagstat{font-size:.88rem;margin:.5rem 0 0;min-height:1.2em}.flagact{display:flex;gap:.6rem;justify-content:flex-end;margin-top:.6rem}.flagact button{font:inherit;cursor:pointer;min-height:44px;padding:.5rem 1.1rem;border-radius:999px}.flagcancel{background:none;border:1px solid var(--edge);color:var(--ink)}.flagsend{background:var(--cyan);color:var(--navy);border:0;font-weight:700}

ul.topics{list-style:none;padding:0;margin:.8rem 0}
ul.topics li{padding:.62rem .2rem;border-bottom:1px solid var(--hair);display:flex;
align-items:baseline;gap:.7rem;flex-wrap:wrap}
ul.topics .tag{font-size:.7rem;font-weight:700;letter-spacing:.12em;color:var(--greytx);
border:1px solid var(--edge);border-radius:6px;padding:.06rem .48rem;flex:none}
ul.topics .meta{color:var(--greytx);font-size:.84rem}
/* .search is the bare filter input and nothing else: the control at the top
   of /biology/definitions/, /biology/key-ideas/, the checklist and every unit
   filter bar. It paints its own card, border and radius because it IS the
   input, so the class must never land on a wrapper. */
.search{width:100%;background:var(--card);border:1px solid var(--edge);border-radius:12px;
color:var(--ink);font:inherit;padding:.62rem .95rem;margin:.4rem 0 .8rem}
.search::placeholder{color:var(--greytx)}
/* .searchbox, not .search, and the difference is the whole point. The search
   page needs a wrapper to hold the input and the results list together, and
   biology called that wrapper .search too -- so on /biology/search/ both rules
   matched, the div drew a rounded grey frame and the input drew a second one
   inside it, and the reader saw a box in a box. Physics found this first and
   maths inherited the fix; biology kept the bug because it was the one
   subject that never got the port. There is deliberately no .searchbox rule
   at all: the wrapper's only job is to be a block, and a rule that said so
   would be the first thing someone added a border to. */
.searchbox input{width:100%;max-width:34rem;padding:.62rem .9rem;border-radius:12px;
border:1px solid var(--edge);background:transparent;color:var(--ink);font:inherit}
/* No outline:none, unlike the rule this replaces. Recolouring the border on
   focus is a nice touch and a poor focus indicator on its own, and both
   siblings dropped the suppression for that reason: a keyboard reader keeps
   the browser's own ring on top of the cyan border. */
.searchbox input:focus{border-color:var(--cyan)}
.searchbox input::placeholder{color:var(--greytx)}
.jumps{color:var(--greytx);font-size:.88rem;line-height:2;margin:.2rem 0 1.2rem}
.jumps a{color:var(--greytx);text-decoration:underline;text-underline-offset:3px;
white-space:nowrap}
.jumps a:hover{color:var(--cyan)}
@media (max-width:560px){
.jumps{line-height:2.35}
/* white-space:normal is not tidying. The base rule keeps a jump link on one
   line, which is right for a short label and wrong here: two canonical unit
   names run past fifty characters, and as unbreakable pills they pushed the
   checklist and the key-ideas page 86px wider than a phone. Wrapping inside
   the pill costs a second line on two rows and stops the whole page
   scrolling sideways. */
.jumps a{display:inline-block;border:1px solid var(--edge);border-radius:99px;
padding:.1rem .68rem;text-decoration:none;margin:0 .06rem;line-height:1.55;
white-space:normal;max-width:100%}
ul.topics li.flt{display:block}
ul.topics li.flt .tag{display:table;margin-top:.45rem;font-size:.74rem}
ul.topics li.flt .meta{display:block;margin-top:.3rem}
}
