
/* InkChemistry, 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.
 */
@font-face{font-family:'Poppins Fallback';font-style:normal;font-weight:400;src:local('Arial'),local('ArialMT'),local('Liberation Sans'),local('LiberationSans'),local('Arimo'),local('Helvetica');size-adjust:111.8%;ascent-override:93.92%;descent-override:31.31%;line-gap-override:8.94%;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212}@font-face{font-family:'Poppins Fallback';font-style:normal;font-weight:500;src:local('Arial'),local('ArialMT'),local('Liberation Sans'),local('LiberationSans'),local('Arimo'),local('Helvetica');size-adjust:113.1%;ascent-override:92.84%;descent-override:30.95%;line-gap-override:8.84%;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212}@font-face{font-family:'Poppins Fallback';font-style:normal;font-weight:700;src:local('Arial Bold'),local('Arial-BoldMT'),local('Liberation Sans Bold'),local('LiberationSans-Bold'),local('Arimo Bold'),local('Helvetica Bold');size-adjust:106.7%;ascent-override:98.41%;descent-override:32.80%;line-gap-override:9.37%;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212}: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);--green:var(--ink-success);--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)}[data-subject="chemistry"]{--subject-accent:var(--ink-amber)}html{-webkit-text-size-adjust:100%}body{overflow-wrap:break-word}.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:.2rem 0 .2rem .6rem;border-left:1px solid var(--ink-edge);opacity:.85}.brandpar:hover,.brandpar:focus-visible{opacity:1}.brandpar .wmsvg{height:18px;width:auto}@media(max-width:420px){.brandpar{padding:.35rem 0 .35rem .42rem}.brandpar .wmsvg{height:13px;width:auto}.brandrow{gap:.42rem}header.site .wrap{column-gap:.4rem}header.site .navbtn{margin-left:auto}.brandrow .brandsub:not(:only-child) .wmsvg{max-width:calc(100vw - 14rem)}}nav.top a[aria-current]{color:var(--subject-accent);opacity:1;border-bottom:2px solid var(--subject-accent)}.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}.acctop{position:relative;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;flex:none;color:var(--ink-text);opacity:.82;text-decoration:none}.acctop:hover,.acctop:focus-visible{opacity:1;text-decoration:none}.acctop svg{width:21px;height:21px}.acctop .accdot{display:none}.acctop.on .accdot{display:block;position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--ink-cyan);border:2px solid var(--ink-bg)}@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 .fgh{font-size:.75rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-muted);margin:0 0 .5rem;font-weight:600;line-height:1.3}.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:.75rem;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}a.beta{text-decoration:none}a.beta:hover,a.beta:focus-visible{color:var(--ink-text);border-color:var(--ink-muted)}.ink-consent{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--bg,#0d1b2a);border-top:1px solid var(--edge,#d9dee6);box-shadow:0 -8px 30px rgba(0,0,0,.45);padding:1rem 1.1rem 1.15rem;padding-bottom:calc(1.15rem + env(safe-area-inset-bottom,0px));max-height:80vh;overflow-y:auto}.ink-consent[hidden]{display:none}.ink-consent .wrap{max-width:52rem;margin:0 auto}.ink-consent .ink-ch{font-size:1rem;margin:0 0 .35rem;line-height:1.3;font-weight:700;display:flex;align-items:center;gap:.6rem;text-wrap:balance}.ink-consent .ink-ch::before{content:"";width:.48rem;height:.48rem;border-radius:50%;background:var(--cyan);flex:none}.ink-consent p{margin:0 0 .8rem;font-size:.9rem;line-height:1.5;color:var(--ink,#0d1b2a)}.ink-consent a{color:var(--cyan,#0aa2c0);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.18em}.ink-consent a:hover{text-decoration-thickness:2px}.ink-consent a:focus-visible{outline:2px solid var(--cyan,#0aa2c0);outline-offset:2px;border-radius:2px}.ink-cbtns{display:flex;gap:.6rem;flex-wrap:wrap}.ink-cbtns button{flex:1 1 11rem;font:inherit;font-size:.92rem;font-weight:600;padding:.6rem 1rem;border-radius:12px;cursor:pointer;border:1.5px solid var(--edge,#d9dee6);background:var(--card,#fff);color:var(--ink,#0d1b2a);min-height:44px}.ink-cbtns button:hover{border-color:var(--cyan,#0aa2c0)}@media (max-width:30rem){.ink-consent{padding:.65rem 1rem .7rem;padding-bottom:calc(.7rem + env(safe-area-inset-bottom,0px))}.ink-consent .wrap{padding:0;font-size:.78rem;line-height:1.4}.ink-consent .ink-ch,.ink-consent p{display:inline;font-size:inherit;line-height:inherit}.ink-consent .ink-ch{margin:0 .3em 0 0}.ink-consent p{margin:0}.ink-cbtns{flex-wrap:nowrap;gap:.5rem;margin-top:.6rem}.ink-cbtns button{flex:1 1 0;min-width:0;font-size:.84rem;padding:.4rem .25rem}}@media print{.ink-consent{display:none}}#ink-consent-h:focus{outline:none}button[data-consent-open]{font:inherit;color:var(--cyan,#0aa2c0);background:none;border:0;padding:0;text-decoration:underline;cursor:pointer}.titlerow{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}.titlerow h1,.titlerow h2{margin:0}.helpbub{display:inline-block}.helpbub>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:1.6rem;height:1.6rem;border:1px solid var(--ink-muted,#84919f);border-radius:50%;color:var(--ink-muted,#84919f);font-size:.85rem;font-weight:700;line-height:1;margin:0;padding:0;flex:none}.helpbub>summary::-webkit-details-marker{display:none}.helpbub>summary::marker{content:''}.helpbub>summary::after{content:none;display:none}.helpbub>summary:hover,.helpbub>summary:focus-visible{color:var(--cyan,#38b6ff);border-color:var(--cyan,#38b6ff)}.helpbub[open]>summary{color:var(--cyan,#38b6ff);border-color:var(--cyan,#38b6ff)}.helpbub[open]{display:block;width:100%;margin:.6rem 0 0}.helppanel{border:1px solid var(--ink-edge,#21f5f5f5);border-radius:14px;background:var(--ink-card,rgba(245,245,245,.035));padding:1rem 1.2rem;max-width:var(--wpanel,47rem)}.helppanel h2{font-size:1.05rem;margin:1.1rem 0 .35rem}.helppanel h2:first-child{margin-top:0}.helppanel p{margin:0 0 .35rem}.helppanel .hn{color:var(--cyan,#38b6ff);font-size:.95rem}.helpbox{display:flex;gap:.5rem;flex-wrap:wrap;margin:.6rem 0 .2rem;padding:0;list-style:none}.helpbox li{flex:1 1 3.2rem;text-align:center;border-radius:8px;border:1px solid var(--ink-edge,#21f5f5f5);padding:.45rem .2rem;font-size:.8rem;color:var(--ink-muted,#84919f)}.helpbox li b{display:block;color:var(--ink,#f5f5f5);font-size:.95rem}@media print{.helpbub>summary{display:none}.helpbub{display:block}.helppanel{border:0;padding:0}}.card[hidden]{display:none}.bdask{border:1px solid var(--ink-edge,#21f5f5f5);border-radius:16px;background:var(--ink-card,rgba(245,245,245,.035));padding:1.1rem 1.2rem;margin:.2rem 0 1.4rem;max-width:var(--wpanel,47rem)}.bdask h2{font-size:1.15rem;margin:0 0 .4rem}.bdask p{margin:0 0 .5rem;font-size:.95rem}.bdaskrow{display:flex;flex-wrap:wrap;gap:.5rem;margin:.8rem 0 .6rem}.bdaskrow button,.bdaskrow .bdaskall{font:inherit;font-size:.92rem;min-height:44px;padding:.55rem 1rem;border-radius:14px;cursor:pointer;border:1px solid var(--ink-edge,#21f5f5f5);background:var(--ink-card,rgba(245,245,245,.035));color:var(--ink,#f5f5f5)}.bdaskrow button:hover,.bdaskrow button:focus-visible{border-color:var(--cyan,#38b6ff);color:var(--cyan,#38b6ff)}.bdaskrow .bdaskall{margin-left:auto}@media (max-width:34rem){.bdaskrow button{flex:1 1 8rem}.bdaskrow .bdaskall{margin-left:0;flex-basis:100%}}.bdaskfoot{font-size:.85rem;color:var(--ink-muted,#84919f)}.bdaskfoot button{font:inherit;font-size:.85rem;background:none;border:0;cursor:pointer;color:var(--cyan,#38b6ff);text-decoration:underline;text-underline-offset:3px;padding:.4rem .3rem;margin-left:.2rem}.bdask.done .bdaskrow,.bdask.done>p:first-of-type{display:none}.bdask.done .bdaskfoot{color:var(--ink,#f5f5f5)}@media print{.bdask{display:none}}.plexlist{list-style:none;padding:0;margin:.4rem 0 .8rem}.plexlist li{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;padding:.5rem 0;border-bottom:1px solid var(--ink-hair,#17f5f5f5)}.plexdel{font:inherit;font-size:.85rem;color:var(--ink-muted,#84919f);background:none;border:0;padding:.4rem .2rem;margin-left:auto;text-decoration:underline;cursor:pointer;min-height:44px}.plexdel:hover,.plexdel:focus-visible{color:var(--coral,#ef476f)}.plexadd{display:flex;flex-direction:column;gap:.6rem;align-items:stretch}.plexadd label{display:flex;flex-direction:column;gap:.25rem;font-size:.9rem;color:var(--ink-muted,#84919f)}.plexadd input{font:inherit;color:var(--ink,#f5f5f5);background:var(--ink-card,rgba(245,245,245,.035));border:1px solid var(--ink-edge,#21f5f5f5);border-radius:10px;padding:.55rem .7rem;min-height:44px}.plexu>summary{cursor:pointer;padding:.4rem 0;font-size:.95rem}.plexwarn{flex:1 1 100%;margin:0;font-size:.9rem;line-height:1.45;color:var(--ink,#f5f5f5);border-left:3px solid var(--amber,#ffb703);padding:.35rem .7rem}.plexwarn:empty{display:none}@media(min-width:34rem){.plexadd{flex-direction:row;flex-wrap:wrap;align-items:flex-end}.plexadd label{flex:1 1 10rem}.plexu{flex:1 1 100%}}.plsheet{border:1px solid var(--ink-edge,#21f5f5f5);border-radius:16px;padding:.2rem 1rem;margin:1.4rem 0}.plsheet>summary{cursor:pointer;font-weight:700;min-height:44px;display:flex;align-items:center}.plsheet[open]>summary{margin-bottom:.6rem}.figdesc{margin-top:.6rem;font-size:.88rem;line-height:1.55;color:var(--greytx)}.figdesc summary{font-size:.85rem}.figdesc p{margin:.45rem 0 0}@media print{.figdesc{display:none}}.liec{margin:0 0 .9rem}.liec:last-child{margin-bottom:0}.liel{color:var(--coral);font-weight:700;font-style:normal}.liec p{display:inline;margin:0;font-style:italic}.liec p::before{content:'\201C'}.liec p::after{content:'\201D'}.boardtools{list-style:none;margin:1.3rem 0 1.5rem;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(11.5rem,1fr));gap:.55rem;max-width:var(--wtext)}.boardtools li{margin:0;padding:0}.boardtools li::before{content:none;display:none}.boardtools a{display:flex;align-items:center;height:100%;min-height:44px;box-sizing:border-box;padding:.5rem .95rem;border:1px solid var(--edge);border-radius:12px;color:var(--ink);font-weight:600;font-size:.94rem;line-height:1.3;text-decoration:none}.boardtools a:hover,.boardtools a:focus-visible{border-color:var(--cyan);color:var(--cyan)}.boardintro{margin-top:.5rem}.boardgaps{font-size:.94rem;line-height:1.9}.boardgaps b{font-weight:700}@media (max-width:560px){.boardtools{grid-template-columns:1fr 1fr;gap:.45rem}.boardtools a{padding:.45rem .7rem;font-size:.9rem}}
:root{--wtext:42rem;--wpanel:47rem;--wfig:58rem}
@font-face{font-family:'Poppins';font-weight:400;font-style:normal;font-display:optional;
src:url('/chemistry/assets/fonts/poppins-400.woff') format('woff')}
@font-face{font-family:'Poppins';font-weight:500;font-style:normal;font-display:optional;
src:url('/chemistry/assets/fonts/poppins-500.woff') format('woff')}
@font-face{font-family:'Poppins';font-weight:700;font-style:normal;font-display:optional;
src:url('/chemistry/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('/chemistry/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('/chemistry/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}
/* What is left of the figure palette, which was the whole of it until the
   drawings moved out of the page on 29 August 2026.

   The drawing engine writes class names onto every line, shape and label and
   never writes a colour, so a drawing that takes its palette from here and
   does not find it renders in the browser default: black text on the navy
   panel and geometry with no stroke at all. The library shipped that way
   once, because every gate inspected the SVG string rather than the
   rendering. What changed is where a drawing gets its palette: every one of
   them is now an <img> at a published file, and figfiles.standalone resolves
   the colours into the file, because a file saved to a school's shared drive
   has no stylesheet beside it.

   So fifteen of these seventeen rules stopped matching anything and cssgate
   named them. The two that remain are not a palette any more; they are the
   colours of two UI icons that happen to be drawn as SVG and carry the class
   -- ARROW_I in sk-cyan and CROSS_I in sk-coral. Which colours survive here
   is a fact about those two icons and nothing more, so an icon that starts
   using amber needs its rule written back, and no gate can ask for it: a
   missing rule matches nothing and nothing complains. */
.figsvg .sk-cyan{stroke:var(--cyan)}.figsvg .sk-coral{stroke:var(--coral)}
/* And nine more from 7 September 2026, written that morning for the
   unit-overview drawing on /chemistry/photosynthesis/ and kept, later the same
   day, for a different set of drawings entirely.

   They were written because that drawing was the library's first figure not on
   a lesson: the published names were minted from the drawings each lesson
   shows, so it had no file to point at, _fig drew it inline, and the page
   stylesheet was the only palette there was. It shipped black-on-navy with no
   stroke in the first build of it and gate 8's colour check named all nine
   classes by figure.

   A hub's drawings are published as files now -- unit_figs_map says why -- so
   that drawing carries its own colours and is no user of anything here any
   more. All nine rules stayed anyway, and which ones stayed was measured
   rather than reasoned from this paragraph: the class attribute of every
   drawing still written out inline was collected off the built pages, and each
   of these nine is worn by at least one of them. sk-grey and tx-grey by
   eighteen drawings and seventeen; tx-coral by one, the Bohr-shift graph a
   question is set on. The population that keeps them is the twenty drawings
   the question bank is set on and the Hill-reaction apparatus on the practical
   guide, which is the same population the six rules below serve.

   The rest of the palette stays deleted, because cssgate refuses a rule with
   no user and an unused colour is exactly what was cleared out in August. When
   an inline drawing is next published or dropped, the rules to delete with it
   are the ones no other inline drawing wears, and that is a count off the
   built tree rather than a reading of this comment. */
.figsvg .sk-amber{stroke:var(--amber)}.figsvg .sk-grey{stroke:var(--grey)}
.figsvg .fl-amber{fill:var(--amber)}.figsvg .fl-coral{fill:var(--coral)}
.figsvg .fl-grey{fill:var(--grey)}
.figsvg .tx-amber{fill:var(--amber)}.figsvg .tx-coral{fill:var(--coral)}
.figsvg .tx-cyan{fill:var(--cyan)}.figsvg .tx-grey{fill:var(--greytx)}
/* And the last six, from the same morning and the same cause on a larger
   scale. The twenty drawings the question bank is set on stopped being
   published as files -- lesson_figs_map says why -- so they draw inline too,
   and these are the classes they use that the eleven rules above do not
   already carry. Found before the build rather than after it: the figure
   modules were loaded the way load_figures loads them and every sk-, fl- and
   tx- class on those twenty drawings collected, which is the same population
   gate 8's colour check would have named one at a time.

   The Hill-reaction apparatus, on the practical guide, is inline for the same
   reason and was not in that count. It cost nothing: every class it wears is
   already among these seventeen. That is luck rather than a rule, and the
   count that catches the next such drawing is gate 8's, not this list.

   sk-bg and fl-bg are not decoration. A drawing knocks a hole in what is
   under it by painting the ground colour over it -- the halo behind a label
   crossing a grid line, the gap a leader line is drawn through -- so a
   missing fl-bg is not a colour that fails to appear but a shape that stops
   hiding what it was drawn to hide.

   Still not the whole palette: sk-greytx, fl-greytx and tx-bg have no user in
   this library and stay deleted, because cssgate refuses a rule with no user.
   Every one of these six is in the app's FIGURE_PALETTE_CSS already, which is
   what lets the same markup draw the same colours on the phone. */
.figsvg .sk-ink{stroke:var(--ink)}.figsvg .sk-bg{stroke:var(--bg)}
.figsvg .fl-ink{fill:var(--ink)}.figsvg .fl-cyan{fill:var(--cyan)}
.figsvg .fl-bg{fill:var(--bg)}.figsvg .tx-ink{fill:var(--ink)}
/* The font stack for figure labels went with the palette on 29 August 2026,
   and for the same reason: no label is set by this stylesheet any more.
   figfiles.standalone writes InkGlyphs first, then Poppins, and no system-ui
   anywhere in the list, into each published file. That order is correctness
   rather than taste -- the drawing engine positions every label by computing
   its width from the font it expects, so a label rendered in a face with
   different metrics lands in the wrong place, overlaps the geometry beside it
   or runs outside the viewBox, and system-ui was the real hazard because it
   resolves differently on every operating system. Counted before deleting:
   259 elements on the built pages carry the figsvg class and not one of them
   contains a <text>; they were the two UI icons above.

   That count stopped being true on 7 September 2026, and the deletion is
   still right. Twenty-one drawings are inline again -- the twenty the
   questions are set on and the Hill-reaction apparatus -- and every one of
   them does carry labels. They need no rule here because they already inherit
   the one the body sets, Poppins then InkGlyphs and no system-ui, the same two
   faces in the same roles as the published files: Poppins carries the Latin
   the labels were measured in, and InkGlyphs is declared over the symbol
   ranges Poppins does not cover, so a Greek letter reaches the same face
   whichever name is written first. A rule repeating that here would be a
   second statement of one fact, and the one that is not the body rule is the
   one that would drift. */
*{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','Poppins Fallback',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. Chemistry 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;column-gap:.4rem}header.site .navbtn{margin-left:auto}
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.
   Chemistry 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 chemistry 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)}
/* 22 October 2026: .75rem (12px), from .72rem, here and on .lieh, .toch,
   th, .pnl and .wbblock .gl below: the lesson labels were the last text on
   a chemistry page under the 12px floor. .qm takes its size from .qh. */
.lieh,.exh,.caph,.priorh,.qh{font-size:.75rem;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:.75rem;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:.75rem;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,.figbox img{display:block;width:100%;height:auto}
/* An animated drawing is a <picture>: the SVG in a <source> so that is what
   renders, the GIF as the <img> so an image search has a moving frame it can
   index and a reader has something to copy. A <picture> is an inline box by
   default, which would wrap a block-level <img> in an inline formatting
   context and leave a baseline gap under the artwork; it is the artwork's own
   box here, so it says so. */
.figbox picture{display:block}
/* 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,.figscroll img{min-width:var(--figmin,0)}
.figscroll picture{display:block}
.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,.figdlgpan img{width:900px;max-width:none;display:block;margin:0 auto}
.figdlgpan picture{display:block}
@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}
.tblwrap{overflow-x:auto;margin:1.2rem auto}
th,td{padding:.5rem .65rem;border-bottom:1px solid var(--hair);text-align:left;
vertical-align:top}
th{font-size:.75rem;text-transform:uppercase;letter-spacing:.08em;color:var(--greytx);
font-weight:600}
/* The route maps at phone width. Four columns is right for a table a reader
   scans; it is wrong for these, where the third column is a list of lesson
   titles up to 709 characters long. .wrap keeps 1.2rem of padding on each
   side, so a 390px phone has about 351px of usable width, and the four
   columns cannot all reach their minimum inside it: the wrapper's overflow-x
   takes over and Coverage, the verdict this page exists to publish, is the
   column you have to scroll sideways to reach. At 320px it is worse. So below
   the phone breakpoint each row becomes a block: ref, heading, where it is
   taught, verdict, in the order the columns already read. The header row goes
   out of the flow rather than being dropped, so its labels stay in the
   accessibility tree; the one cell that loses a heading it needed says what
   it is; and the empty cell on a row no lesson teaches disappears rather than
   leaving a blank line. Only the route tables do this, which is what .spec is
   for: a lesson's table is narrow enough already. */
@media (max-width:560px){
table.spec thead{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip-path:inset(50%)}
table.spec,table.spec tbody,table.spec tr,table.spec th,table.spec td{display:block;width:auto}
table.spec tbody tr{padding:.85rem 0;border-bottom:1px solid var(--hair)}
table.spec td{padding:.12rem 0;border:0}
table.spec td:empty{display:none}
table.spec td:nth-child(3)::before{content:"Taught in: ";color:var(--greytx)}
}
.scroll{overflow-x:auto;margin:1.4rem 0;max-width:var(--wpanel)}
/* The material a question is set on, wherever a question is shown: a graph to
   read a rate off, a micrograph to measure, a table of results to process. Its
   children are the lesson's own items and carry the lesson's own rules, so
   this block does nothing but space it: the figure or table sits closer to the
   stem it belongs to than to the mark scheme under it, which is what says the
   two are one question rather than a question and an illustration. */
.qsrc{margin:.55rem 0 1.1rem}
.qsrc>.fig,.qsrc>.scroll{margin-top:0}
/* 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;overflow-wrap:break-word}
/* 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.
   17 October 2026: a grid rather than a flex row, because the code, the h2
   and the sentence are the summary's own children now (an h2 may not sit in
   the span that used to hold them). Column one is what that span was, flex:1
   and min-width:0; column two is the chevron, centred across all three rows
   as it was centred on the span. */
details.cap>summary{display:grid;grid-template-columns:minmax(0,1fr) auto;
column-gap:.9rem;align-items:center;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>*{grid-column:1}
details.cap>summary::-webkit-details-marker{display:none}
details.cap>summary::after{content:'';grid-column:2;grid-row:1/span 3;
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)}
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;flex-wrap:wrap;justify-content:space-between;gap:.3rem 1rem;margin-bottom:.5rem}
/* 3 November 2026: the board chip may wrap. brand.py sets it nowrap, which in
   a flex row (li.ck, p.qh) made "AQA · OCR A · Edexcel · CAIE" wider than a
   360px screen on seven lessons (regression crawl). */
body .tqbd{white-space:normal;overflow-wrap:anywhere}
li.ck>.cktext,li.ck>.tqbd{min-width:0}
.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}
/* 2 November 2026: a levelled scheme. The two headings and the level bands
   under the indicative content of a six-mark question (build._scheme_html). */
.schemeh{margin:.7rem 0 0;font-size:.75rem;font-weight:700;letter-spacing:.06em;
text-transform:uppercase;color:var(--greytx)}
ul.levels{list-style:none;margin:.35rem 0 0;padding:0;font-size:.95rem}
ul.levels li{margin:.38rem 0}
/* 21 October 2026: .75rem (12px), from .74rem. */
.mcode{font-size:.75rem;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:.75rem;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:.75rem;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 chemistry'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 pill app.js builds in the app header. Hidden until the script
   adds .on -- the app layer's own rule, the mechanism physics uses. An
   attribute-gated variant from before the .on path shipped sat here; nothing
   ever set its attribute, so it matched nothing and is gone. */
.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}
/* The poster wall. Each poster is a 2:3 image and the aspect-ratio is
   declared so the grid does not reflow as they load; the images carry their
   own navy, so the tile is a border and nothing else.

   Three destinations per tile and they are deliberately different: the sheet
   opens the full-size PNG, the title goes to the lesson, and the download
   saves the file. The tile used to be one link to the lesson, which made the
   poster the only thing on a page of posters you could not click through to. */
.posters{display:grid;grid-template-columns:repeat(auto-fill,minmax(15rem,1fr));gap:1.1rem;margin:1.4rem 0 2.2rem;padding:0;list-style:none}
.posters li{border:1px solid var(--edge);border-radius:16px;overflow:hidden;background:var(--card)}
.posters li:hover{border-color:rgba(56,182,255,.5)}
.postersheet{display:block;transition:transform .18s cubic-bezier(.2,.9,.3,1.25)}
.postersheet:hover{transform:scale(1.015)}
.posters img{display:block;width:100%;height:auto;aspect-ratio:2/3;background:var(--bg)}
.posterfoot{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;padding:.7rem .85rem}
.postertitle{font-weight:700;font-size:.95rem;color:var(--ink)}
.posterdl{display:inline-flex;align-items:center;gap:.25rem;font-size:.82rem;font-weight:500;white-space:nowrap;color:var(--cyan)}
.posterdl .pi{width:1em;height:1em;flex:none}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
/* The print block, whose core is brand.PRINT_CSS and which chemistry 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 chemistry'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 img{filter:invert(1) hue-rotate(180deg) contrast(1.15) brightness(1.06)}
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}
.tqbdnote button{display: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:.75rem;color:#0D1B2A;width:1.15rem;height:1.15rem;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.5rem;height:1.5rem;margin-top:0;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:-10px}.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}.gdef dd>a{font-size:.88rem}.gdef dd>a::before{content:"· ";color:var(--greytx)}.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:.75rem;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}@media (scripting:enabled){.fcbar[hidden]{display:block;visibility:hidden}}.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:.75rem;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}.fccard .eqs{margin:.9rem auto}.fccard .eqs .eq{font-size:clamp(1rem,3.4vw,1.25rem)}@media print{.fcbar,#fcplayer{display:none}}.fcbar{background:var(--card);border:1px solid var(--edge);border-radius:20px;padding:1rem 1.2rem 1.2rem}.fcbar .fchead{margin:0 0 .6rem;font-size:1.02rem}.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)}.fcscope .fcfixed{margin:0;display:flex;align-items:center;font-size:.82rem;color:var(--greytx)}
.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:.75rem;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-top:.35rem;padding-bottom:.35rem;min-height:44px;display:flex;align-items:center}.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}.tqcode{border:1px solid var(--hair);border-radius:6px;padding:.05rem .4rem;letter-spacing:.08em}.tqbd{border:1px solid rgba(56,182,255,.45);border-radius:99px;padding:.05rem .5rem;color:var(--cyan);white-space:nowrap}.tqbdnote{color:var(--greytx);font-size:.88rem;margin:1.2rem 0 0}.tqbdnote button{font:inherit;background:none;border:0;padding:.6rem .2rem;color:var(--cyan);text-decoration:underline;text-underline-offset:3px;cursor:pointer}h2[hidden]{display:none}.tqq:target{border-left:3px solid var(--cyan);padding-left:.85rem;scroll-margin-top:5rem}.tqgap{color:var(--greytx);font-size:.88rem;margin:1.2rem 0 0}.tqhow{margin:.9rem 0 0}.tqhow summary{min-height:44px}.tqhow ul{margin:.2rem 0 0;padding-left:1.15rem;color:var(--greytx);font-size:.92rem}.tqhow li{margin:.3rem 0}.qdir{margin:2.2rem 0 0;border-top:1px solid var(--hair);padding-top:1.2rem}.qdir h3{font-size:.95rem;margin:1.2rem 0 .3rem}.qdirlist{list-style:none;padding:0;margin:.3rem 0;columns:2;column-gap:2.2rem}.qdirlist li{margin:.28rem 0;break-inside:avoid}.qdirlist .meta{color:var(--greytx);font-size:.8rem}@media(max-width:560px){.qdirlist{columns:1}}.tqrail{margin:2.2rem 0 0;border-top:1px solid var(--hair);padding-top:1.2rem}.tqrail h2{font-size:1.05rem}.tqpn{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin:1.1rem 0 0;font-size:.92rem}.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-family:inherit;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{font-family:inherit;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)}.qbalt{font:inherit;font-weight:600;font-size:.95rem;padding:.6rem 1.2rem;border-radius:999px;background:none;color:var(--ink);border:1px solid var(--edge);cursor:pointer;min-height:44px}.qbalt:hover,.qbalt:focus-visible{border-color:var(--cyan)}.qbalt[hidden]{display:none}.qbpick{font-size:.95rem;margin:1.2rem 0 .4rem}.qbfold{border-bottom:1px solid var(--edge)}.qbfold>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}.qbfold>summary::-webkit-details-marker{display:none}.qbfold>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}.qbfold[open]>summary::after{transform:rotate(-135deg)}.qbfold>summary:hover .ubt,.qbfold>summary:focus-visible .ubt{color:var(--cyan)}.qbfoldb{padding:.1rem 0 1.1rem}.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:.75rem;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:.75rem;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:.75rem;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:.75rem;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,.flagdlg 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:.75rem;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}.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}.stheat{display:grid;grid-template-columns:repeat(7,1fr);gap:5px;margin:.6rem 0 1.2rem;max-width:340px}.stheat b{font:inherit;font-weight:500;font-size:.75rem;color:var(--greytx);text-align:center;line-height:1}.stheat i{display:block;aspect-ratio:1;border-radius:4px;background:var(--hair)}.stheat i.d{background:var(--green)}.stheat i.p{background:var(--amber)}.stheat i.m{background:var(--coral)}.stkey{display:flex;flex-wrap:wrap;gap:.35rem .9rem;font-size:.75rem;color:var(--greytx);margin:0 0 1.2rem}.stkey span{display:inline-flex;align-items:center;gap:.35rem}.stkey i{width:10px;height:10px;border-radius:3px;background:var(--hair);flex:none}.stkey i.d{background:var(--green)}.stkey i.p{background:var(--amber)}.stkey i.m{background:var(--coral)}.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:.75rem}}@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:.75rem;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,border-color .18s}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}
.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:.75rem;min-height:0;padding:.15rem .1rem}.flagrow{margin:.6rem 0 0}@media print{.flagbtn,.lsec>.flagbtn,.flagrow{display:none}}.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)}.flagbd{margin:0 0 .8rem}.flagbd select{width:100%;box-sizing:border-box}.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}
.plset{margin:.4rem 0 1.4rem}.plset fieldset{border:0;padding:0;margin:0 0 1.5rem;min-width:0}.plset legend{font-weight:700;font-size:1.05rem;padding:0;margin:0 0 .2rem}.plset .meta{margin:0 0 .7rem}.plopts{display:flex;flex-wrap:wrap;gap:.5rem}.plopt{font:inherit;font-size:.95rem;font-weight:600;padding:.55rem 1.1rem;border-radius:999px;cursor:pointer;min-height:44px;border:1px solid var(--edge);background:var(--bg);color:var(--ink)}.plopt:hover{border-color:var(--cyan)}.plopt[aria-pressed=true]{background:var(--cyan);border-color:var(--cyan);color:var(--navy)}.pldays .plopt{min-width:3.4rem;padding:.55rem .5rem;text-align:center}.plsum{border:1px solid var(--edge);border-radius:16px;padding:.9rem 1.1rem;margin:.2rem 0 1.4rem;font-size:.95rem;color:var(--greytx)}.plsum b{color:var(--ink)}.pldots{display:flex;gap:.2rem;margin:.2rem 0 1.1rem}.pldot{flex:1 1 0;height:.36rem;border-radius:3px;background:var(--edge);min-width:2px}.pldot.on{background:var(--cyan)}.pldot.at{background:var(--amber)}.plkind{font-size:.75rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--cyan);margin:0 0 .5rem}.plles h2{margin:.1rem 0 .5rem;font-size:1.3rem}.plles h2::before{display:none}.plles .meta{margin:0 0 1rem}.plflip{cursor:pointer}.pldone{text-align:center;padding:1.8rem 1rem 1.6rem}.plring{display:block;margin:0 auto .9rem;width:104px;height:104px}.plring circle{fill:none;stroke-width:6;stroke-linecap:round}.plring .trk{stroke:var(--edge)}.plring .arc{stroke:var(--cyan);stroke-dasharray:295;stroke-dashoffset:0;transform:rotate(-90deg);transform-origin:50% 50%}.plring .tk{fill:none;stroke:var(--cyan);stroke-width:7;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:44;stroke-dashoffset:0}.plgo .plring .arc{animation:plarc .9s ease-out both}.plgo .plring .tk{animation:pltk .45s .75s ease-out both}.plgo .pldone .big{animation:plpop .5s .9s ease-out both}@keyframes plarc{from{stroke-dashoffset:295}to{stroke-dashoffset:0}}@keyframes pltk{from{stroke-dashoffset:44}to{stroke-dashoffset:0}}@keyframes plpop{from{opacity:0;transform:translateY(.4rem) scale(.94)}to{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.plgo .plring .arc,.plgo .plring .tk,.plgo .pldone .big{animation:none}}.plbackbar{position:fixed;left:0;right:0;bottom:0;z-index:59;display:flex;justify-content:center;padding:.6rem .8rem calc(.6rem + env(safe-area-inset-bottom));background:linear-gradient(to top,var(--bg) 62%,rgba(13,27,42,0))}.plbackbar button{font:inherit;font-weight:700;font-size:.95rem;padding:.62rem 1.5rem;border-radius:999px;background:var(--cyan);color:var(--navy);border:0;cursor:pointer;min-height:44px;box-shadow:0 6px 22px rgba(0,0,0,.4)}body.hasplanbar{padding-bottom:4.5rem}@media (display-mode: standalone){.plbackbar{bottom:calc(72px + env(safe-area-inset-bottom));padding-bottom:.6rem}body.hasplanbar{padding-bottom:calc(4.5rem + 72px + env(safe-area-inset-bottom))}}@media print{.plbackbar{display:none}}

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}
/* 21 October 2026: the spec-code tag at .75rem (12px), from .7rem, and
   from .74rem in the phone layout below; it was the most numerous text
   under 12px on the site (147 on the physics AQA spec page). */
ul.topics .tag{font-size:.75rem;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 /chemistry/definitions/, /chemistry/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
   chemistry called that wrapper .search too -- so on /chemistry/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; chemistry 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)}
/* The per-unit practise button on the flashcards hub. brand.py draws the
   button itself, for all three subjects; where it sits in a browse row is this
   library's own decision and so is here, exactly as physics's equivalent pair
   is in physics's build.
   No display property, and that is load-bearing rather than an omission. The
   button ships with the hidden attribute and flashcards.js takes it off when a
   player exists, so any display here would put a control that can do nothing
   back on a page with scripting off. */
.fcdir li{margin:.45rem 0}
.fcdir .fcpr{margin-left:.45rem;vertical-align:middle}
.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:.75rem}
ul.topics li.flt .meta{display:block;margin-top:.3rem}
}
