/* Tradeonomist — marketing site.
   ==========================================================================
   THREE RULES, each of which the previous version broke and tools/audit-site.py
   now enforces.

   1. TYPE SCALE. Eleven sizes, named. v2 had 27 arbitrary values, which is not
      a scale — it is 27 separate decisions nobody can keep consistent.

   2. FONT ROLES, one job each.
        --display  Fraunces      headings and large numerals ONLY
        --body     IBM Plex Sans ALL prose, including captions
        --mono     IBM Plex Mono labels, eyebrows, tabular data, chart text
      v2 had prose captions set in mono, which reads badly and was a large part
      of why the site felt incoherent.

   3. TEXT COLOUR vs FILL COLOUR are different things.
      On these dark grounds only --text and --muted clear 4.5:1 everywhere; a
      third, dimmer text grey is mathematically impossible (--muted is already
      only 4.85 on the lightest panel). So --dim exists for HAIRLINES AND
      INACTIVE MARKS and must never carry text. --clay likewise fails as text
      (3.63 on raised) and has --clay-text for when it must be read.
   ========================================================================== */

:root{
  color-scheme:dark;

  /* grounds */
  --ink:#0D0F16; --panel:#171B26; --raised:#1F2433;

  /* text — every one of these clears 4.5:1 on all three grounds */
  --text:#DFDBCE; --muted:#8B90A0;
  --gold:#C9A227; --sage:#7C9473; --info:#7A93A8; --clay-text:#C6765B;

  /* fills and marks — NOT for text */
  --clay:#B5654A; --dim:#5A6070;
  --line:rgba(237,234,224,.10); --line-strong:rgba(237,234,224,.18);

  /* faces */
  --display:'Fraunces',Georgia,'Times New Roman',serif;
  --body:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,Menlo,Consolas,monospace;

  /* scale */
  --track-label:.085em; --track-tight:-.02em;
  --t-micro:11px; --t-label:12px; --t-small:13px; --t-cap:14px;
  --t-base:14.5px;--t-body:15.5px;--t-lead:17.5px;--t-h3:17px;
  --t-num:27px;   --t-big:34px;

  --wrap:1080px; --read:66ch;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}}

body{margin:0;background:var(--ink);color:var(--text);
  font-family:var(--body);font-size:var(--t-body);line-height:1.7;
  -webkit-font-smoothing:antialiased}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 24px}
.narrow{max-width:var(--wrap)}
.narrow > *{max-width:72ch}
.narrow > .actions{max-width:none}
.narrow > .lede{max-width:none}
a{color:var(--gold);text-decoration:none}
a:hover{text-decoration:underline}
:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:4px}

/* ---------------------------------------------------------------- header */
header{position:sticky;top:0;z-index:50;background:rgba(13,15,22,.9);
  backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
.nav{display:flex;align-items:center;gap:28px;height:64px}
.brand{font-family:var(--display);font-variation-settings:'opsz' 22,'SOFT' 0,'WONK' 0;font-weight:700;font-size:22px;letter-spacing:var(--track-tight);
  color:var(--text);text-decoration:none;margin-right:auto;white-space:nowrap}
.brand span{color:var(--gold)}
.nav .links{display:flex;align-items:center;gap:24px;flex-wrap:wrap}
.nav .tab{font-family:var(--body);font-size:var(--t-cap);color:var(--muted);
  text-decoration:none;padding:6px 2px;border-bottom:2px solid transparent;
  background:none;border-top:none;border-left:none;border-right:none;
  cursor:pointer;line-height:inherit}
.nav .tab:hover{color:var(--text);text-decoration:none}
.nav .tab[aria-current="page"]{color:var(--text);border-bottom-color:var(--gold)}
.nav .cta{font-family:var(--body);background:var(--gold);color:#141100;font-weight:600;
  font-size:var(--t-cap);padding:9px 16px;border-radius:9px;white-space:nowrap}
.nav .cta:hover{background:#dcb32c;text-decoration:none}
/* MOBILE NAV. No JS on this site (script-src 'none'), so no hamburger.
   The previous attempt let the whole nav wrap: the brand took a full row of
   its own, which pushed the CTA onto a second row hard against the right edge
   and the six links onto a third. Three ragged rows, ~150px of a 667px screen
   spent on navigation, and the CTA reading as an accident rather than a
   button.

   Now two rows that each do one job: brand and CTA side by side, then the
   links as a single horizontally scrollable strip -- the same pattern a phone
   uses for category tabs. The six links total ~410px at this size against
   ~327px of usable width, so they cannot all fit; scrolling is honest about
   that where wrapping just looked broken. The right-edge fade is what says
   there is more. */
@media (max-width:880px){
  .nav{flex-wrap:wrap;height:auto;padding:12px 0 0;gap:0}
  .brand{margin-right:auto;width:auto;font-size:20px}
  .nav .cta{order:2;padding:8px 14px}
  .nav .links{order:3;width:100%;margin-top:11px;flex-wrap:nowrap;
    overflow-x:auto;gap:20px;scrollbar-width:none;-ms-overflow-style:none}
  .nav .links::-webkit-scrollbar{display:none}
  .nav .tab{white-space:nowrap;padding-bottom:9px}
  /* The current page moves to the head of the strip on mobile ONLY. The strip
     scrolls, so on /pricing the gold underline sat past the right edge and the
     one tab that tells you where you are was the one you could not see. No JS
     here to scroll it into view, and ordering costs nothing: the strip already
     has no meaningful sequence, and every phone-sized category bar puts the
     active item first for exactly this reason. Desktop shows all six at once
     and keeps the authored order. */
  .nav .tab[aria-current="page"]{order:-1}
  /* Signals the strip continues past the edge. pointer-events:none so it never
     eats a tap on the link underneath.

     NO `position:relative` on header here -- that was in the first draft and it
     silently un-stuck the header on phones, which is where a sticky CTA is
     worth the most. `position:sticky` already establishes a containing block
     for an absolutely positioned child, so the override bought nothing and
     cost the behaviour. */
  header::after{content:'';position:absolute;right:0;bottom:1px;width:40px;height:36px;
    background:linear-gradient(to left,var(--bg) 30%,rgba(13,15,22,0));pointer-events:none}
}
.skip{position:absolute;left:-9999px;top:8px;z-index:99;background:var(--panel);
  border:1px solid var(--line-strong);color:var(--text);padding:10px 16px;border-radius:8px}
.skip:focus{left:8px}

/* ------------------------------------------------------------------ type */
h1,h2{font-family:var(--display);font-weight:400;letter-spacing:var(--track-tight);
  text-wrap:balance;margin:0;color:var(--text);
  font-variation-settings:'opsz' 40,'SOFT' 0,'WONK' 0}
h1{font-size:clamp(27px,3.6vw,36px);line-height:1.2}
h2{font-size:clamp(20px,2.2vw,24px);line-height:1.32;margin-bottom:12px;
  font-variation-settings:'opsz' 27,'SOFT' 0,'WONK' 0}
/* h3 is a CARD TITLE, not a headline. In the serif at 18px it read as a
   magazine subhead; in the sans it reads as a product. Fraunces is now
   reserved for h1/h2 and large numerals, which is what a display face is for. */
h3{font-family:var(--body);font-weight:500;font-size:var(--t-h3);line-height:1.36;
  margin:0 0 7px;color:var(--text);text-wrap:balance}
p{margin:0 0 16px}
.lede{font-size:var(--t-lead);line-height:1.65;color:var(--muted)}
.eyebrow{font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--gold);margin:0 0 14px}
.muted{color:var(--muted)}
section{padding:64px 0}
/* Two sections on the SAME ground have no band edge between them, so the full
   stacked padding reads as a void rather than as a boundary. On an alternating
   pair the same space is the inside margin of a colour band and earns itself. */
section:not(.alt) + section:not(.alt),
section.alt + section.alt{padding-top:22px}
/* The hero already ended with space; the next section must not restate it. */
.hero + section{padding-top:44px}
.hero + section.tight{padding-top:36px}
section.alt{background:var(--panel)}
section.tight{padding:44px 0}
.sechead{margin-bottom:34px}
.sechead h2{margin-bottom:10px}
.sechead p{margin:0;font-size:var(--t-lead);color:var(--muted)}
.sechead p + p{margin-top:15px}
/* The paragraph FLOWS ACROSS TWO COLUMNS rather than being capped at 60ch.
   That fills the container edge to edge while each line stays about 46
   characters -- one column across 1080px would set ~110-character lines,
   which is roughly twice a comfortable measure. */
.sechead.wide{max-width:none}
.sechead.wide > p{max-width:none;column-count:2;column-gap:52px}
@media (max-width:820px){.sechead.wide > p{column-count:1}}
/* `.full` is the short-paragraph case: release the cap and let one line run
   edge to edge. Two columns would give it a line and a half each, which reads
   as a broken layout rather than a considered one. */
.sechead.full{max-width:none}
.sechead.full > p{max-width:none}
/* Same release for a standalone paragraph outside a .sechead. */
.p-full{max-width:none}

/* ------------------------------------------------------------------ hero */
.hero{padding:80px 0 40px}
.hero h1{max-width:17ch;margin-bottom:20px}
/* A short headline that the 17ch measure would break mid-phrase. Only
   worth using when the line is genuinely short enough to fit whole. */
.hero h1.oneline{max-width:none;text-wrap:balance}
.hero .lede{max-width:none}
.herogrid{display:grid;grid-template-columns:1.12fr .88fr;gap:56px;align-items:center}
@media (max-width:900px){.herogrid{grid-template-columns:1fr;gap:44px}}
.actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:30px}
.btn{display:inline-block;padding:13px 24px;border-radius:10px;font-weight:600;
  font-size:var(--t-base);text-decoration:none;border:1px solid transparent}
.btn-primary{background:var(--gold);color:#141100}
.btn-primary:hover{background:#dcb32c;text-decoration:none}
.btn-ghost{border-color:var(--line-strong);color:var(--text)}
.btn-ghost:hover{border-color:var(--gold);color:var(--gold);text-decoration:none}

/* -------------------------------------------------------- rows and cards */
.row{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center}
.row.flip .rowfig{order:-1}
@media (max-width:880px){.row{grid-template-columns:1fr;gap:32px}.row.flip .rowfig{order:0}}
.rowtext p:last-child{margin-bottom:0}
.grid{display:grid;gap:16px}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:24px}
@media (max-width:980px){
  .principles{grid-template-columns:repeat(2,minmax(0,1fr))}
  .g3{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:800px){
  .g3,.g2{grid-template-columns:1fr}
}
@media (max-width:560px){
  .principles{grid-template-columns:1fr}
}
section.alt .card{background:var(--raised)}
.card h3{margin-bottom:8px}
.card p{font-size:var(--t-base);line-height:1.68;margin-bottom:0;color:var(--muted)}
.card .n{font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  color:var(--gold);margin:0 0 10px}

/* ----------------------------------------------------------------- stats */
.statband{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:14px;overflow:hidden}
.statband div{background:var(--ink);padding:22px 20px}
section.alt .statband div{background:var(--panel)}
.statband b{display:block;font-family:var(--display);font-weight:400;font-size:var(--t-num);
  line-height:1;color:var(--text);font-variant-numeric:tabular-nums}
.statband b.g{color:var(--gold)}
.statband span{display:block;font-family:var(--body);font-weight:500;font-size:var(--t-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted);margin-top:10px;line-height:1.5}

/* ----------------------------------------------------------- comparisons */
.vs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
@media (max-width:800px){.vs{grid-template-columns:1fr}}
.vs > div{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:24px}
.vs .them{border-left:3px solid var(--clay)}
.vs .us{border-left:3px solid var(--sage)}
.vs .lbl{font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--muted);margin-bottom:10px}
.vs p{font-size:var(--t-base);color:var(--muted);margin:0}

.principles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:14px;overflow:hidden}
.principles > div{background:var(--ink);padding:24px 22px}
section.alt .principles > div{background:var(--panel)}
.principles h3{font-size:var(--t-body);margin-bottom:7px}
.principles p{font-size:var(--t-cap);color:var(--muted);margin:0}
.principles .no{font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  color:var(--clay-text);display:block;margin-bottom:9px}

/* ----------------------------------------------------------------- lists */
ul.clean{list-style:none;padding:0;margin:0 0 16px}
ul.clean li{position:relative;padding-left:26px;margin-bottom:11px;
  font-size:var(--t-base)}
ul.clean li::before{content:"";position:absolute;left:6px;top:10px;width:6px;height:6px;
  border-radius:50%;background:var(--gold)}

/* ---------------------------------------------------------------- tables */
.tablewrap{overflow-x:auto;border:1px solid var(--line);border-radius:13px;background:var(--panel)}
section.alt .tablewrap{background:var(--raised)}
table{border-collapse:collapse;width:100%;min-width:520px;font-size:var(--t-cap)}
th,td{text-align:left;padding:13px 18px;border-bottom:1px solid var(--line);vertical-align:top}
thead th{font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--muted);font-weight:500}
tbody tr:last-child td{border-bottom:none}
tfoot td{border-top:1px solid var(--line-strong);border-bottom:none;color:var(--text)}
td.num{font-family:var(--body);font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;color:var(--text)}
table.cmp td:nth-child(2),table.cmp td:nth-child(3),
table.cmp th:nth-child(2),table.cmp th:nth-child(3){text-align:center;width:118px}
table.cmp .yes{color:var(--sage);font-weight:600}
table.cmp .no{color:var(--muted)}
table.cmp tbody td:first-child{color:var(--text)}

/* --------------------------------------------------------------- pricing */
/* min(300px,100%) rather than a bare 300px: an auto-fit track will NOT go
   below its floor, so on a 320px phone -- 272px of content once padding is
   taken -- a 300px floor pushes the whole document to 324px and every page
   scrolls sideways. min() lets the track give way when there is no room and
   changes nothing at any width where 300px fits. */
.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:18px;
  align-items:stretch}
.plan{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:28px;
  display:flex;flex-direction:column}
.plan ul.clean{flex:1 0 auto}
.plan .actions{margin-top:auto;padding-top:8px}
.plan.pro{border-color:#8d7220;background:var(--raised)}
.plan .tier{font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--gold);margin:0}
.plan .price{font-family:var(--display);font-variation-settings:'opsz' 34,'SOFT' 0,'WONK' 0;font-size:var(--t-big);font-weight:400;
  line-height:1;margin:14px 0 4px}
.plan .per{font-size:var(--t-cap);color:var(--muted);margin:0}

/* ------------------------------------------------------------- quote/code */
/* The equation is the claim the whole page rests on, so it is a feature rather
   than a code block. It sat on var(--ink) inside an ink section -- the same
   colour as the page, with only a 10%-opacity hairline to separate it. */
.formula{font-family:var(--mono);font-size:var(--t-base);line-height:1.75;
  color:var(--text);background:var(--raised);
  border:1px solid rgba(201,162,39,.34);border-left:3px solid var(--gold);
  border-radius:12px;padding:22px 26px;overflow-x:auto;max-width:none;
  box-shadow:0 12px 34px rgba(0,0,0,.34)}
section.alt .formula{background:var(--ink);box-shadow:none}
/* Each term takes the colour of its own arc in the ring. */
.formula .t-learn{color:var(--gold)}
.formula .t-disc{color:var(--sage)}
.formula .t-win{color:var(--info)}
.pull{border-left:3px solid var(--gold);padding:4px 0 4px 26px;margin:0}
.pull p{font-family:var(--display);font-variation-settings:'opsz' 20,'SOFT' 0,'WONK' 0;font-size:20px;line-height:1.45;color:var(--text);
  margin:0;max-width:44ch}
.pull cite{display:block;font-family:var(--body);font-weight:500;font-size:var(--t-micro);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--muted);font-style:normal;margin-top:14px}

/* ------------------------------------------------------------------- faq */
/* Rows sit directly on the page with a rule between them, rather than as a
   stack of separate panels -- twelve bordered boxes with a gap between each
   reads as twelve things, when it is one list. */
details{border-bottom:1px solid var(--line);padding:2px 0;margin:0}
details:first-of-type{border-top:1px solid var(--line)}
summary{cursor:pointer;font-weight:500;font-size:var(--t-body);list-style:none;
  padding:18px 34px 18px 0;position:relative}
summary:hover{color:var(--gold)}
summary::-webkit-details-marker{display:none}
summary::after{content:"+";position:absolute;right:2px;top:16px;color:var(--gold);
  font-family:var(--body);font-size:20px;line-height:1;font-weight:400}
details[open] summary::after{content:"\2013"}
details p{margin:0 0 20px;max-width:none;color:var(--muted);font-size:var(--t-base)}

/* --------------------------------------------------------------- figures */
.fig{margin:0;padding:0}
.fig svg{width:100%;height:auto;display:block;overflow:visible}
/* Captions are PROSE and are set in the body face. v2 set them in mono, which
   reads badly at caption size and made the page look like three sites. */
/* Captions are an aside about the figure, not part of the argument, so they
   sit a step below the body in size and in weight of voice. */
.fig figcaption{font-family:var(--body);font-style:italic;font-size:var(--t-label);
  line-height:1.6;color:var(--muted);margin-top:14px;max-width:56ch}
.fig text{font-family:var(--body);font-variant-numeric:tabular-nums;fill:var(--muted)}
.fig-ring{display:flex;align-items:center;gap:32px;flex-wrap:wrap}
.fig-ring svg{width:206px;flex:0 0 206px}
.fig .ring-n{font-family:var(--display);font-variation-settings:'opsz' 33,'SOFT' 0,'WONK' 0;font-size:33px;font-weight:400;fill:var(--text)}
.fig .ring-l{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--muted)}
.keys{display:flex;flex-direction:column;gap:14px}
.key{display:flex;align-items:baseline;gap:11px;white-space:nowrap}
.key i{width:11px;height:11px;border-radius:3px;flex:0 0 11px;transform:translateY(1px)}
.key b{font-family:var(--body);font-weight:600;font-variant-numeric:tabular-nums;
  font-size:var(--t-base);color:var(--text);min-width:40px}
.key span{font-size:var(--t-base);color:var(--muted)}
.fig .bar-l{font-size:var(--t-micro);fill:var(--text)}
.fig .bar-v{font-size:var(--t-micro);fill:var(--muted)}
.fig .bar-k{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--muted)}
.fig .rank-n{font-size:var(--t-micro);fill:#0D0F16;font-weight:600;text-anchor:middle}
.fig .rank-t{font-size:var(--t-micro);fill:var(--muted)}
.fig .loop-n{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--gold)}
.fig .loop-t{font-family:var(--body);font-weight:600;font-size:15px;fill:var(--text)}
.fig .spec-l{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--clay-text)}
.fig .spec-m{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--muted)}

/* ---------------------------------------------------------------- device */
.phone{width:262px;border:1px solid var(--line-strong);border-radius:30px;padding:9px;
  background:var(--raised);box-shadow:0 24px 60px rgba(0,0,0,.45);margin:0 auto}
.phone-in{background:var(--ink);border-radius:23px;padding:17px 16px 20px}
/* Everything below is inside an aria-hidden mockup: it depicts an interface at
   reduced scale rather than presenting text to read, which is why it is the one
   place allowed under the 11px floor. audit-site.py knows the .ph- prefix. */
.ph-top{display:flex;justify-content:space-between;align-items:center;font-family:var(--mono);
  font-size:9px;color:var(--muted);margin-bottom:16px}
.ph-dot{width:38px;height:5px;border-radius:3px;background:var(--line-strong)}
.ph-eyebrow{font-family:var(--mono);font-size:8px;letter-spacing:var(--track-label);color:var(--muted);margin:0 0 5px}
.ph-h{font-family:var(--display);font-size:18px;font-weight:600;margin:0 0 13px;color:var(--text)}
.ph-card{background:var(--panel);border:1px solid var(--line);border-radius:11px;
  padding:12px 13px;margin-bottom:9px}
.ph-score{display:flex;justify-content:space-between;align-items:flex-start}
.ph-lbl{font-family:var(--mono);font-size:8px;letter-spacing:var(--track-label);color:var(--muted);margin:0 0 5px}
.ph-big{font-family:var(--display);font-size:34px;font-weight:600;line-height:1;color:var(--gold);margin:0}
.ph-rank{text-align:right}
.ph-rank span{display:block;font-family:var(--mono);font-size:8.5px;color:var(--muted)}
.ph-rank b{display:block;font-family:var(--display);font-size:13px;color:var(--text);margin-top:3px}
.ph-bars{display:flex;flex-direction:column;gap:7px;margin:0 0 11px}
.ph-bars div{display:flex;align-items:center;gap:8px}
.ph-bars span{height:5px;border-radius:3px;background:var(--gold);display:block;flex:0 0 auto}
.ph-bars em{font-family:var(--mono);font-size:8px;font-style:normal;color:var(--muted);letter-spacing:var(--track-label)}
.ph-step{font-size:10.5px;color:var(--muted);margin:0 0 5px;padding-left:15px;position:relative}
.ph-step::before{content:"";position:absolute;left:0;top:4px;width:8px;height:8px;border-radius:50%;
  border:1.5px solid var(--line-strong)}
.ph-step.ph-done{color:var(--text)}
.ph-step.ph-done::before{background:var(--sage);border-color:var(--sage)}
.ph-step:last-child{margin-bottom:0}
.ph-streak{display:flex;align-items:baseline;gap:8px;margin-top:11px;padding-top:11px;
  border-top:1px solid var(--line)}
.ph-streak b{font-family:var(--display);font-size:19px;color:var(--gold)}
.ph-streak span{font-family:var(--mono);font-size:9px;color:var(--muted)}

/* ----------------------------------------------------------------- legal */
.legal h2{font-variation-settings:'opsz' 20,'SOFT' 0,'WONK' 0;font-size:20px;
  margin-top:40px;margin-bottom:12px}
.legal p{color:var(--muted)}
.legal .meta,.meta{font-family:var(--body);font-weight:500;font-size:var(--t-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted);margin:0 0 14px}

/* ---------------------------------------------------------------- footer */
footer{border-top:1px solid var(--line);padding:50px 0 60px;color:var(--muted);
  font-size:var(--t-cap)}
.foot{display:flex;flex-wrap:wrap;gap:34px;justify-content:space-between}
.foot nav{display:flex;flex-wrap:wrap;gap:20px}
.foot a{color:var(--muted)}
.foot a:hover{color:var(--text)}
.disclaim{margin-top:34px;padding-top:22px;border-top:1px solid var(--line);
  font-size:var(--t-small);line-height:1.65;color:var(--muted)}

/* Chart sizing. A 15-row bar chart stretched to container width was the
   curriculum page's whole problem — it is a figure, not a background. */
.fig-cap{max-width:520px}
.fig-wide{max-width:660px}
.fig .flow-h{font-family:var(--body);font-weight:600;font-size:14px;fill:var(--text)}
.fig .flow-s{font-size:var(--t-micro);fill:var(--muted)}
.fig .flow-l{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--muted)}
.fig .flow-x{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--clay-text)}



/* Numbered steps. A sequence, so the numerals carry meaning rather than
   decorating -- and set as a list rather than cards, because the detail lives
   on how-it-works and this is the teaser. */
ol.steps{list-style:none;counter-reset:s;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:28px}
ol.steps li{counter-increment:s;position:relative;padding-top:56px}
/* The step numeral is set in the display face at size, not as a micro label.
   It is the one place on the page where a number is the ornament as well as
   the information, so it can carry weight. */
ol.steps li::before{content:"0" counter(s);position:absolute;top:-4px;left:0;
  font-family:var(--display);font-variation-settings:'opsz' 30,'SOFT' 0,'WONK' 0;
  font-size:30px;font-weight:400;line-height:1;
  letter-spacing:var(--track-tight);color:var(--gold)}
ol.steps li::after{content:"";position:absolute;top:44px;left:0;width:26px;height:1px;
  background:var(--line-strong)}
ol.steps b{display:block;font-weight:500;font-size:var(--t-body);color:var(--text);margin-bottom:5px}
ol.steps span{display:block;font-size:var(--t-base);line-height:1.62;color:var(--muted)}
@media (max-width:800px){ol.steps{grid-template-columns:1fr;gap:22px}}

/* ---------------------------------------------------------------- motion
   CSS only -- _headers sets script-src 'none', so there is no observer and no
   library. Every animation REVEALS the resting state and uses fill-mode both,
   so the figure is complete the moment it finishes and complete immediately
   when motion is reduced. Nothing is ever parked invisible waiting to be
   scrolled to. */
@keyframes candle-in{
  from{opacity:0;transform:translateY(10px) scaleY(.55)}
  to  {opacity:1;transform:none}
}
@keyframes rule-draw{ from{stroke-dashoffset:280} to{stroke-dashoffset:0} }
@keyframes bar-grow{ from{transform:scaleX(0);opacity:.35} to{transform:scaleX(1);opacity:1} }

.cndl{
  transform-box:fill-box;transform-origin:50% 100%;
  animation:candle-in .42s cubic-bezier(.22,.7,.28,1) both;
  animation-delay:calc(var(--i) * 45ms);
}
.rule-in{
  stroke-dasharray:280;
  animation:rule-draw .55s cubic-bezier(.4,0,.2,1) both;
  animation-delay:.34s;
}
.rule-in.rule-late{animation-delay:.5s}
/* Deliberately NO text animation. A label hidden behind a 1.15s delay is the
   content of the figure waiting on a timer, which is the failure this whole
   ruleset exists to avoid. Shapes reveal; words are simply there. */
.barrow{
  transform-box:fill-box;transform-origin:0% 50%;
  animation:bar-grow .54s cubic-bezier(.22,.7,.28,1) both;
  animation-delay:calc(var(--i) * 38ms);
}

/* The global reduced-motion rule collapses these to .01ms, which lands on the
   final keyframe -- the finished figure, instantly. */
@media (prefers-reduced-motion:reduce){
  .cndl,.rule-in,.barrow{animation:none}
  .rule-in{stroke-dasharray:none}
}
.fig .spec-ok{font-size:var(--t-micro);letter-spacing:var(--track-label);fill:var(--sage)}
.fig .ring-c{font-family:var(--body);font-weight:500;font-size:var(--t-micro);
  letter-spacing:var(--track-label);fill:var(--text)}
.fig .yr-m{font-size:var(--t-micro);fill:var(--muted)}

/* ---------------------------------------------------------- signup form */
.signup{display:flex;flex-wrap:wrap;gap:12px;margin-top:26px;align-items:stretch}
.signup input[type=email]{
  flex:1 1 320px;min-width:0;
  background:var(--panel);border:1px solid var(--line-strong);border-radius:10px;
  padding:13px 16px;font-family:var(--body);font-size:var(--t-base);color:var(--text);
}
.signup input[type=email]::placeholder{color:var(--muted)}
.signup input[type=email]:focus-visible{outline:2px solid var(--gold);outline-offset:2px;
  border-color:var(--gold)}
.signup .btn{flex:0 0 auto;border:0;cursor:pointer;font-family:var(--body)}
/* Off-screen rather than display:none, so it is submitted and reachable by the
   bots that fill every field, while never shown or focusable. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.formnote{margin-top:14px;font-size:var(--t-small)}
@media (max-width:520px){.signup .btn{flex:1 1 100%;text-align:center}}

/* ------------------------------------------------------------- spacing
   Three steps, because the pages had accumulated eleven ad-hoc inline
   margin values (12/16/18/20/20/22/22/26/26/34/34) -- the same not-a-system
   fault the 27 font sizes and 11 tracking values had, and the reason spacing
   inside sections read as uneven. */
:root{--sp-1:14px; --sp-2:22px; --sp-3:34px}
.mt-1{margin-top:var(--sp-1)}
.mt-2{margin-top:var(--sp-2)}
.mt-3{margin-top:var(--sp-3)}
.mb-3{margin-bottom:var(--sp-3)}
.foot-tag{margin:8px 0 0;font-size:var(--t-small);max-width:34ch}

/* "More" links. The arrow is drawn by CSS rather than typed into the copy, so
   it cannot drift between links, and the nudge on hover gives the affordance
   without needing an underline. */
.more{display:inline-flex;align-items:baseline;gap:8px;font-weight:500;
  font-size:var(--t-base);text-decoration:none}
.more::after{content:"\2192";transition:transform .18s ease}
.more:hover{text-decoration:none}
.more:hover::after{transform:translateX(4px)}
@media (prefers-reduced-motion:reduce){.more::after{transition:none}}
.fig .drift-v{font-size:var(--t-micro);fill:var(--text);font-variant-numeric:tabular-nums}
.fig .drift-g{font-size:var(--t-micro);fill:var(--muted)}
.fig .drift-k{font-size:var(--t-micro);fill:var(--muted)}
/* The bar chart's caption explains the bars, which begin 152 units in, past
   the category labels. Aligning it to the figure's left edge put it under the
   labels instead of under what it describes. */
.fig-bars figcaption{padding-left:152px}
@media (max-width:560px){.fig-bars figcaption{padding-left:0}}

/* A sample of real lesson titles. Titles are catalogue metadata; the lessons
   themselves are the product, and the Terms forbid bulk-extracting them --
   publishing one verbatim sat oddly beside that. */
ul.titles{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:52px}
ul.titles li{display:grid;grid-template-columns:1fr auto;align-items:baseline;gap:16px;
  padding:15px 0;border-bottom:1px solid var(--line)}
.tl-title{font-size:var(--t-base);line-height:1.45;color:var(--text)}
.tl-meta{font-family:var(--body);font-weight:500;font-size:var(--t-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted);
  white-space:nowrap}
@media (max-width:760px){
  ul.titles{grid-template-columns:1fr}
  ul.titles li{grid-template-columns:1fr;gap:5px}
  .tl-meta{white-space:normal}
}

/* ------------------------------------------------- billing period toggle
   No JavaScript: two radios and sibling selectors. Kept focusable (opacity,
   not display:none) so the switch works from the keyboard. */
.cyc{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
/* Two separate buttons rather than one segmented pill: each carries its own
   border, so the choice reads as two things you pick between. */
.cycle{display:flex;gap:8px;margin:18px 0 14px}
.cycle label{font-family:var(--body);font-weight:500;font-size:var(--t-micro);
  letter-spacing:var(--track-label);text-transform:uppercase;
  padding:10px 18px;border:1px solid var(--line-strong);border-radius:9px;
  cursor:pointer;color:var(--muted);background:none;transition:border-color .15s ease,color .15s ease}
.cycle label:hover{color:var(--text);border-color:var(--muted)}
#cyc-m:checked ~ .cycle label[for="cyc-m"],
#cyc-y:checked ~ .cycle label[for="cyc-y"]{background:var(--gold);border-color:var(--gold);
  color:#141100;font-weight:600}
@media (prefers-reduced-motion:reduce){.cycle label{transition:none}}
#cyc-m:focus-visible ~ .cycle label[for="cyc-m"],
#cyc-y:focus-visible ~ .cycle label[for="cyc-y"]{outline:2px solid var(--gold);outline-offset:2px}
.prices .p-y,.note-y{display:none}
#cyc-y:checked ~ .prices .p-m,
#cyc-y:checked ~ .note-m{display:none}
#cyc-y:checked ~ .prices .p-y,
#cyc-y:checked ~ .note-y{display:block}
.plan .prices p{margin:0}
.plan .price s{color:var(--muted);text-decoration-thickness:1px;margin-right:10px;
  font-size:.62em;font-weight:400}

/* ------------------------------------------------------------ legal page */
.legal h2{display:flex;align-items:center;gap:12px}
.lg-mark{order:-1;display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;flex:0 0 34px;border-radius:9px;
  background:var(--panel);border:1px solid var(--line);color:var(--gold)}
.lg-icon{width:19px;height:19px;display:block}

/* ------------------------------------------------------------------ modal
   :target, not script — _headers sets script-src 'none'. The veil is a link
   back to "#", which is how clicking outside closes it with no handler. */
.modal{position:fixed;inset:0;z-index:100;display:none}
.modal:target{display:grid;place-items:center;padding:24px}
.modal-veil{position:absolute;inset:0;background:rgba(5,6,10,.74);backdrop-filter:blur(3px)}
.modal-card{position:relative;width:min(520px,100%);background:var(--panel);
  border:1px solid var(--line-strong);border-radius:18px;padding:34px 36px;
  box-shadow:0 30px 80px rgba(0,0,0,.6);max-height:90vh;overflow-y:auto}
.modal-card h2{margin-bottom:10px}
.modal-card > p{max-width:none}
.modal-x{position:absolute;top:12px;right:16px;font-size:1.7em;line-height:1;
  color:var(--muted);text-decoration:none}
.modal-x:hover{color:var(--text);text-decoration:none}
.modal .signup{margin-top:22px}
.modal .signup input[type=email]{flex:1 1 100%}
.modal .signup .btn{flex:1 1 100%;text-align:center}
/* Fine print: terms that qualify what is above them, at the same size as the
   footer disclaimer so the site has one voice for small legal text. */
.fineprint{font-size:var(--t-small);line-height:1.65;color:var(--muted)}

/* Separates the FAQ's two halves -- what it does, then what it refuses to do.
   The order is deliberate: the page used to open with three consecutive
   refusals, so the first thing a curious visitor read was what the product
   would not give them. */
.faqbreak{margin:38px 0 14px;padding-top:26px;border-top:1px solid var(--line)}

/* The three steps that open each paragraph on /how-it-works. Gold rather than
   bold-on-body, so the sequence is scannable before a word of it is read --
   the paragraphs are dense and the step names were doing no work at all. */
.stepword{color:var(--gold);font-weight:600}
