/* Shared shell for every page. One file so the learner side and the admin side
   cannot drift into looking like two different products.

   Bright and plain: white, black, soft greys, rounded corners, one sans-serif.
   Colour is kept for the two things that need it to carry meaning, the chart
   series and the warning and error notes. Everything else is black on white,
   or white on black in the dark theme.

   Themes. The site is white for everyone, whatever their computer is set to.
   The toggle in the top bar (src/theme.js) switches to dark by writing
   data-theme="dark" on <html>, and remembers the choice. */

@import url("https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,400..700&display=swap");

:root{
  /* Form controls (checkboxes, scrollbars) follow the theme. */
  color-scheme:light;
  --ground:#FFFFFF; --surface:#FFFFFF; --surface-2:#F5F5F5; --surface-3:#EBEBEB;
  /* --ink-3 is small grey text: counts, page numbers, citations. 5.3:1 on white. */
  --ink:#0A0A0A; --ink-2:#3F3F3F; --ink-3:#6B6B6B;
  --rule:#E7E7E7; --grid:#EFEFEF;
  /* The accent is black. --accent-ink is the text that sits on it. */
  --accent:#0A0A0A; --accent-ink:#FFFFFF; --accent-soft:#F1F1F1;
  --bad:#B42318; --bad-soft:#FEF1EF;
  --warn:#8A5300; --warn-soft:#FFF6E5;

  /* Chart series. Data marks keep their colour in a black and white design:
     two grey bars cannot carry which series is which. Both pairs pass the
     lightness band, chroma floor, colour-vision separation, normal-vision
     floor and contrast against their own surface. */
  --s1:#2C6FB5; --s2:#B26A12;
  --s1-soft:#DCE8F4; --s2-soft:#F2E7D5;

  --shadow-sm:0 1px 2px rgba(0,0,0,.04),0 1px 3px rgba(0,0,0,.05);
  --shadow-md:0 2px 6px rgba(0,0,0,.04),0 10px 30px rgba(0,0,0,.07);
  --focus:0 0 0 3px rgba(10,10,10,.14);

  --r-sm:8px; --r-md:12px; --r-lg:18px; --r-xl:24px; --r-pill:999px;

  --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  /* --serif is kept as a name so older rules follow the new type. Nothing on
     the site is set in a serif any more. */
  --serif:var(--sans);
  --mono:ui-monospace,SFMono-Regular,Menlo,monospace;
}

:root[data-theme="dark"]{
  color-scheme:dark;
  --ground:#0A0A0A; --surface:#141414; --surface-2:#1C1C1C; --surface-3:#262626;
  --ink:#FAFAFA; --ink-2:#C9C9C9; --ink-3:#9B9B9B;
  --rule:#262626; --grid:#1F1F1F;
  --accent:#FAFAFA; --accent-ink:#0A0A0A; --accent-soft:#262626;
  --bad:#F97066; --bad-soft:#2B1512;
  --warn:#F5B547; --warn-soft:#2A2010;
  --s1:#4E95D6; --s2:#BE8128;
  --s1-soft:#1B2B3C; --s2-soft:#2C2416;
  --shadow-sm:0 1px 2px rgba(0,0,0,.5);
  --shadow-md:0 2px 6px rgba(0,0,0,.4),0 10px 30px rgba(0,0,0,.45);
  --focus:0 0 0 3px rgba(250,250,250,.22);
}

*{box-sizing:border-box;}
html,body{margin:0;}

/* The hidden attribute is only a user-agent display:none, so any author rule
   that sets display (button, .btn and .msg.show below all do) quietly wins
   and the element stays on screen. Every page here toggles hidden and means
   it. */
[hidden]{display:none !important;}

/* For words a screen reader needs and a sighted reader already has from the
   layout, such as the count on a filter chip. */
.visually-hidden{position:absolute !important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
/* The page ground is painted by the ROOT element. If it only lived on body it
   would propagate to the canvas, which paints outside the theme wipe's view
   transition, and the background would snap while everything else wiped. */
html{background:var(--ground);scroll-behavior:smooth;}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto;}}
/* The top bar is sticky, so a jump to an anchor stops short of it. */
[id]{scroll-margin-top:84px;}
@media print{html{background:#fff;}}
body{
  background:var(--ground);color:var(--ink);
  font:16px/1.6 var(--sans);
  font-optical-sizing:auto;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--ink);text-underline-offset:3px;text-decoration-thickness:1px;text-decoration-color:var(--ink-3);}
a:hover{text-decoration-color:var(--ink);}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{
  outline:2px solid var(--ink);outline-offset:2px;
}

/* ---- shell ---------------------------------------------------------------- */
.topbar{
  background:color-mix(in srgb,var(--ground) 86%,transparent);
  -webkit-backdrop-filter:saturate(1.6) blur(14px);backdrop-filter:saturate(1.6) blur(14px);
  border-bottom:1px solid var(--rule);position:sticky;top:0;z-index:20;
}
.topbar-in{
  max-width:1080px;margin:0 auto;padding:12px 22px;
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
}
/* The mark is the site's logo, drawn as a mask so it is black on white and
   white on black without a second file. */
.wordmark{
  display:inline-flex;align-items:center;gap:9px;
  font-size:1.02rem;font-weight:650;letter-spacing:-.015em;
  color:var(--ink);text-decoration:none;white-space:nowrap;
}
.wordmark::before{
  content:"";width:24px;height:24px;flex:0 0 auto;background:var(--ink);
  -webkit-mask:url("/mark.svg") center/contain no-repeat;mask:url("/mark.svg") center/contain no-repeat;
}
.topbar nav{margin-left:auto;display:flex;align-items:center;gap:2px;flex-wrap:wrap;}
.topbar nav a,.topbar nav button{
  font:inherit;font-size:.92rem;font-weight:500;padding:7px 13px;border:0;border-radius:var(--r-pill);
  background:transparent;color:var(--ink-2);cursor:pointer;text-decoration:none;box-shadow:none;
}
.topbar nav a:hover,.topbar nav button:hover{color:var(--ink);background:var(--surface-2);filter:none;}
.topbar nav a[aria-current="page"],.topbar nav button[aria-pressed="true"]{
  color:var(--accent-ink);background:var(--accent);
}
.page{max-width:1080px;margin:0 auto;padding:40px 22px 96px;}
.narrow{max-width:720px;}

h1,h2,h3{font-family:var(--sans);font-weight:650;letter-spacing:-.02em;}
h1{font-size:2rem;line-height:1.15;letter-spacing:-.03em;margin:0 0 10px;}
h2{font-size:1.25rem;line-height:1.3;margin:0 0 6px;}
h3{font-size:1.05rem;line-height:1.35;margin:0 0 4px;letter-spacing:-.012em;}
.hint{font-size:.94rem;color:var(--ink-2);margin:0 0 14px;}

/* A section break the way a journal does one: a rule with the heading sitting
   on it, rather than another box around everything. */
.sectionhead{
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  margin:0 0 20px;padding-bottom:12px;border-bottom:1px solid var(--rule);
}
.sectionhead h2{margin:0;font-size:1.4rem;letter-spacing:-.025em;}
.sectionhead p{margin:0;font-size:.9rem;color:var(--ink-3);}

.card{background:var(--surface);border:1px solid var(--rule);border-radius:var(--r-lg);
      padding:24px 26px;margin-bottom:18px;box-shadow:var(--shadow-sm);}
.card > h2{margin-bottom:2px;}

/* ---- forms ---------------------------------------------------------------- */
label{display:block;font-size:.84rem;font-weight:550;color:var(--ink-2);margin-bottom:6px;}
input,select,textarea{
  width:100%;padding:11px 14px;font:inherit;font-size:.97rem;border-radius:var(--r-md);
  background:var(--surface);color:var(--ink);border:1px solid var(--rule);
  transition:border-color .15s,box-shadow .15s;
}
input:hover,select:hover,textarea:hover{border-color:var(--ink-3);}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--ink);box-shadow:var(--focus);}
input[type=checkbox],input[type=radio]{width:auto;box-shadow:none;}
.row{display:grid;gap:14px;margin-bottom:14px;}
@media (min-width:640px){
  .row.two{grid-template-columns:1fr 1fr;}
  .row.three{grid-template-columns:1fr 1fr 1fr;}
}
.actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center;}
/* Buttons are pills: black with white text, white with black text in the dark
   theme. A quiet button is outlined. */
button,.btn{
  font:inherit;font-weight:550;font-size:.94rem;line-height:1.2;padding:11px 20px;cursor:pointer;
  border-radius:var(--r-pill);background:var(--accent);color:var(--accent-ink);border:1px solid var(--accent);
  text-decoration:none;display:inline-block;transition:opacity .15s,background-color .15s,border-color .15s;
}
button:hover,.btn:hover{opacity:.86;}
button.quiet,.btn.quiet{background:var(--surface);color:var(--ink);border-color:var(--rule);}
button.quiet:hover,.btn.quiet:hover{background:var(--surface-2);border-color:var(--ink-3);opacity:1;}
button[disabled]{opacity:.4;cursor:default;}

.msg{margin-top:14px;font-size:.93rem;padding:12px 15px;border-radius:var(--r-md);display:none;}
.msg.show{display:block;}
.msg.ok{background:var(--accent-soft);color:var(--ink);}
.msg.bad{background:var(--bad-soft);color:var(--bad);}
.linkout{
  margin-top:14px;padding:13px 15px;background:var(--surface-2);border:1px solid var(--rule);border-radius:var(--r-md);
  font-family:var(--mono);font-size:.82rem;word-break:break-all;display:none;
}
.linkout.show{display:block;}

/* ---- tables --------------------------------------------------------------- */
.scroller{overflow-x:auto;margin-top:16px;border:1px solid var(--rule);border-radius:var(--r-lg);background:var(--surface);}
table{border-collapse:collapse;width:100%;font-size:.92rem;}
th,td{text-align:left;padding:10px 14px;border-bottom:1px solid var(--rule);vertical-align:top;}
th{font-size:.8rem;color:var(--ink-3);font-weight:550;background:var(--surface-2);white-space:nowrap;}
tbody tr:last-child td{border-bottom:0;}
tbody tr:hover{background:var(--surface-2);}
td.num{font-variant-numeric:tabular-nums;white-space:nowrap;}

.pill{font-size:.78rem;font-weight:550;padding:3px 10px;border-radius:var(--r-pill);display:inline-block;
      background:var(--surface-2);color:var(--ink-2);white-space:nowrap;}
.pill.done{background:var(--accent);color:var(--accent-ink);}
.pill.warn{background:var(--warn-soft);color:var(--warn);}
.empty{color:var(--ink-3);padding:24px 0;font-size:.95rem;}

/* ---- stat tiles ----------------------------------------------------------- */
.tiles{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));margin-bottom:18px;}
.tile{background:var(--surface);border:1px solid var(--rule);border-radius:var(--r-lg);padding:20px 22px;box-shadow:var(--shadow-sm);}
.tile .n{
  font-size:2.1rem;font-weight:650;line-height:1.05;font-variant-numeric:tabular-nums;
  letter-spacing:-.035em;display:block;
}
.tile .k{font-size:.85rem;color:var(--ink-2);margin-top:6px;display:block;}
.tile .sub{font-size:.8rem;color:var(--ink-3);margin-top:2px;display:block;}

/* ---- charts --------------------------------------------------------------- */
.charts{display:grid;gap:18px;align-items:start;}
@media (min-width:820px){.charts.two{grid-template-columns:1fr 1fr;}}
figure{margin:0;background:var(--surface);border:1px solid var(--rule);border-radius:var(--r-lg);padding:22px 24px 18px;box-shadow:var(--shadow-sm);}
figcaption{font-size:1.05rem;font-weight:650;letter-spacing:-.015em;margin-bottom:2px;}
.figsub{font-size:.85rem;color:var(--ink-3);margin-bottom:16px;}
.legend{display:flex;gap:18px;flex-wrap:wrap;font-size:.84rem;color:var(--ink-2);margin-bottom:12px;}
.legend span{display:flex;align-items:center;gap:7px;}
.swatch{width:11px;height:11px;flex:0 0 auto;border-radius:3px;}
svg{display:block;width:100%;height:auto;overflow:visible;}
.tick{font-size:10px;fill:var(--ink-3);font-variant-numeric:tabular-nums;}
.barlabel{font-size:10.5px;fill:var(--ink-2);font-variant-numeric:tabular-nums;}
.axisname{font-size:11px;fill:var(--ink-3);}
.gridline{stroke:var(--grid);stroke-width:1;}

/* ---- the archive: filters, entries, contents --------------------------------
   Shared by the archive and the landing page. Entries are divided by hairline
   rules with a small grey line for where each was printed. The filters are
   rounded chips: grey when off, black when on. */
.facets{display:grid;gap:12px;margin:0 0 22px;}
/* baseline: when the chips wrap to a second row, the label stays beside the
   first row instead of floating between the two. */
.facet{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;}
.facet-k{flex:0 0 100%;font-size:.9rem;font-weight:600;color:var(--ink-2);padding-top:6px;}
@media (min-width:720px){.facet-k{flex:0 0 5.2rem;}}
.facet-chips{display:flex;flex-wrap:wrap;gap:8px;flex:1 1 0;min-width:0;}
.facet-tools{display:flex;flex-wrap:wrap;align-items:center;gap:8px 22px;padding-top:2px;}

.chip{
  font:inherit;font-size:.9rem;font-weight:500;line-height:1.3;padding:8px 14px;border-radius:var(--r-pill);
  display:inline-flex;align-items:baseline;gap:8px;cursor:pointer;
  background:var(--surface-2);color:var(--ink);border:1px solid transparent;
}
.chip:hover{opacity:1;background:var(--surface-3);}
.chip .n{font-size:.8rem;color:var(--ink-3);font-variant-numeric:tabular-nums;}
.chip[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);}
.chip[aria-pressed="true"] .n{color:inherit;opacity:.82;}
/* A chip that would show nothing stays tappable, since the empty answer is
   itself worth knowing, but it does not compete with the ones that would. */
.chip.none:not([aria-pressed="true"]){color:var(--ink-3);background:transparent;border:1px dashed var(--rule);}
/* A filter the search read out of the query, with its own remove control. */
.chip.on{background:var(--surface);border-color:var(--ink);color:var(--ink);}
.chip.on .x{font-size:1rem;line-height:1;}
.chip.on:hover{background:var(--surface-2);}

.check{display:inline-flex;align-items:center;gap:8px;margin:0;font-size:.93rem;font-weight:400;color:var(--ink-2);cursor:pointer;}
.check input{margin:0;accent-color:var(--accent);width:17px;height:17px;flex:0 0 auto;}
/* A button that reads as a link: for small actions beside a list. */
.linkish{background:none;border:0;padding:0;color:var(--ink);font:inherit;font-size:.93rem;font-weight:500;
  text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px;cursor:pointer;border-radius:0;}
.linkish:hover{opacity:.7;}

.entries{list-style:none;margin:0;padding:0;border-top:1px solid var(--rule);}
.entry{padding:16px 0 18px;border-bottom:1px solid var(--rule);overflow-wrap:anywhere;}
.entry.go{cursor:pointer;}
/* Where an entry was printed: small grey text in sentence case. */
.entry-where{font-size:.84rem;color:var(--ink-3);margin:0 0 4px;}
.entry h3{font-size:1.12rem;line-height:1.32;margin:0 0 3px;}
.entry h3 a{color:var(--ink);text-decoration:none;}
.entry h3 a:hover,.entry.go:hover h3 a{text-decoration:underline;}
.entry-by{font-size:.92rem;color:var(--ink-2);margin:0 0 8px;}
.entry-facts{list-style:none;margin:0;padding:0;font-size:.9rem;color:var(--ink-2);}
.entry-facts li{margin:3px 0;}
.entry-facts .k{color:var(--ink);font-weight:600;}
.entry-note{display:block;font-size:.84rem;color:var(--ink-3);}
.entry .snip{margin:4px 0 10px;font-size:.93rem;color:var(--ink-2);}
.entry mark{background:var(--surface-3);color:var(--ink);font-weight:600;padding:0 3px;border-radius:4px;}
.entry-go{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 16px;margin:0;font-size:.9rem;}
.entry-go a{font-weight:600;}
.entry-go span{color:var(--ink-3);}
.subhead{font-size:1.05rem;font-weight:650;
  color:var(--ink-2);margin:34px 0 0;padding-bottom:8px;}

/* An issue's own contents page: the printed section heads, each line a title
   with its page set to the right, as the journal sets it. */
.toc-sec{margin:34px 0 0;padding-bottom:10px;border-bottom:1px solid var(--rule);font-size:1.2rem;}
.toc{list-style:none;margin:0;padding:0;}
.toc li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 18px;padding:11px 0;
  border-bottom:1px solid var(--rule);overflow-wrap:anywhere;}
.toc .t{font-size:1rem;font-weight:500;line-height:1.4;}
.toc .t a{color:var(--ink);text-decoration:none;}
.toc .t a:hover{text-decoration:underline;}
.toc .pg{grid-column:2;grid-row:1;font-size:.88rem;color:var(--ink-3);text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap;}
.toc .by,.toc .gr{grid-column:1;font-size:.88rem;color:var(--ink-2);}
.toc .gr{color:var(--ink-3);}
@media (max-width:420px){.toc .pg{white-space:normal;max-width:8.5rem;}}

/* The one line a visitor who is not a member sees about reading. */
.gate-line{font-size:.95rem;color:var(--ink-2);margin:0 0 26px;padding:14px 18px;
  background:var(--surface-2);border-radius:var(--r-md);}

/* ---- theme toggle and the theme wipe ----------------------------------------
   Ported from the Impact Suite. The new theme is revealed as a circle growing
   from the point that was clicked, using the View Transitions API. Browsers
   without it, and people who ask for reduced motion, get an instant switch. */
.theme-toggle{
  width:36px;height:36px;padding:0;border-radius:var(--r-pill);flex:0 0 auto;
  display:inline-flex;align-items:center;justify-content:center;
  background:transparent;color:var(--ink-2);border:1px solid var(--rule);
}
.theme-toggle:hover{background:var(--surface-2);color:var(--ink);opacity:1;}
/* On a page whose top bar has no nav, or hides it until you sign in, push the
   toggle to the right edge. */
.topbar-in > .wordmark + .theme-toggle,.topbar-in > nav[hidden] + .theme-toggle{margin-left:auto;}
/* On a phone the nav can't share a line with the name, so it gets a row of its
   own and the toggle stays up beside the name. */
@media (max-width:560px){
  .topbar-in{row-gap:6px;}
  .topbar-in > .theme-toggle{order:2;margin-left:auto;}
  .topbar-in > nav{order:3;flex-basis:100%;margin-left:-13px;}
}
.theme-toggle svg{width:17px;height:17px;display:block;overflow:visible;}
@keyframes theme-reveal{
  from{clip-path:circle(0px at var(--wipe-x,0px) var(--wipe-y,100%));}
  to{clip-path:circle(var(--wipe-r,160%) at var(--wipe-x,0px) var(--wipe-y,100%));}
}
/* Chrome sets mix-blend-mode:plus-lighter on the two snapshots so its default
   cross-fade stays energy-preserving. This is not a cross-fade: the old frame
   is held and the new one revealed over it, so plus-lighter would add the two
   themes together inside the circle. Composite normally and unstack them. */
::view-transition-image-pair(root){isolation:auto;}
::view-transition-old(root),::view-transition-new(root){mix-blend-mode:normal;}
::view-transition-old(root){animation:none;z-index:0;}
::view-transition-new(root){animation:theme-reveal 640ms cubic-bezier(.16,1,.3,1);z-index:1;}
/* Element transitions would fight the wipe and muddy its edge. */
html.theme-wipe *,html.theme-wipe *::before,html.theme-wipe *::after{transition:none !important;}
@media (prefers-reduced-motion:reduce){::view-transition-old(root),::view-transition-new(root){animation:none;}}
