/* ============================================================
   Western Language Academy — shared stylesheet (PROTOTYPE)
   ------------------------------------------------------------
   This is step 1 of the plan, built for real: one place for the
   tokens and components that are currently copy-pasted into a
   separate <style> block on each of 10 pages.

   Typeface: Poppins, kept per your decision. Authority comes
   from weight and letter-spacing instead of a second family —
   headings sit at 600/700 with tight tracking rather than 800.
   ============================================================ */

/* ---------- 1. TOKENS ----------
   Light = "Daylight". Dark = "Midnight", rebuilt as a real dark mode
   (dark surfaces, not a light page with a dark band). Everything below
   section 2 is theme-agnostic: no component rule names a colour
   literal, which is why the dark theme is one block instead of a
   second stylesheet. */
:root{
  color-scheme:light;

  /* colour */
  --navy:#0e2439;          /* headings */
  --blue:#0a5fb4;          /* links, active states */
  --blue-2:#176fbd;
  --sky:#f1f7fe;           /* tint surface */
  --orange:#ef6c12;       /* GRAPHICS only: bars, rings, active borders */
  --orange-2:#ff9a4c;     /* the lighter end of an orange gradient/ring */
  --orange-fill:#bf5209;  /* button fills that carry white text (4.7:1) */
  /* Was #c1570e, tuned to 4.53:1 against white. The Practice Center puts
     it on --app-bg (#f5f8fb) instead, where that dropped to 4.25:1.
     Retuned against the TINT, so it clears 4.5 on both: 4.61 / 4.91. */
  --orange-text:#b9520d;  /* orange as text on any light surface */
  --on-orange:#ffffff;    /* text on an orange fill */
  --orange-ink:#b45009;   /* 4.7:1 on --orange-soft; #b8530b measured 4.49 */
  --orange-soft:#fef3ea;
  --ink:#16283c;           /* body text */
  --muted:#5f7183;        /* 5.2:1 on white */
  --muted-2:#6c7884;      /* 4.5:1 — small meta text still has to pass */
  --line:#e9eef4;          /* hairline */
  --line-2:#f4f7fa;
  --paper:#fff;            /* cards */
  --bg:#fff;               /* page */
  --green:#178557;
  --green-soft:#e9f8f1;
  --red:#c64d4d;
  --thumb-bg:#eef3f8;      /* backing behind a game thumbnail */
  --thumb-fill:linear-gradient(140deg,#f2f7fb,#e6eef6);
  --surface-2:#fafcfe;     /* hover / open tint, one step off the card */
  --surface-3:#f8fbfe;     /* card-button fill */
  --border-strong:#aac1d6; /* outlined control */
  --border-hover:#aac5dc;
  --nav-ink:#526275;
  --topbar-bg:rgba(255,255,255,.96);
  --menu-bg:rgba(255,255,255,.98);
  --orange-hover:#a8480a;
  --solid-bg:#0e2439;      /* the "Sign up" style button */
  --solid-ink:#ffffff;
  --solid-hover:#16324e;
  --chip-base:#ffffff;     /* what a chip tint mixes toward */
  --dot-idle:#d8e2ec;
  --focus-ring:rgba(10,95,180,.12);
  --pathdark:linear-gradient(135deg,#0c3156,#0864ad);
  --footer-bg:#0e2439;
  --footer-ink:#c8d6e4;
  --footer-dim:#a8bccf;
  --footer-base:#8fa8c0;
  --footer-rule:rgba(255,255,255,.16);
  --callout-bg:#fffaf4;
  --callout-line:#f0d3b8;
  --callout-ico:#ffe8d7;
  --callout-ink:#5b6979;
  --code-bg:#f6e6d5;
  --page-header-grad:linear-gradient(115deg,#f3f8fd,var(--paper) 62%);
  --page-header-ring:rgba(10,95,180,.05);

  /* ---- app surfaces (Practice Center) ----
     The marketing pages sit on white. The Practice Center is an app
     shell: the page is tinted so cards read as raised off it. On dark
     the page is already the darkest surface, so --app-bg == --bg. */
  --app-bg:#f5f8fb;

  /* Deep panels — the mock-exam hero and the exam-date card. Stored as
     colour STOPS, not whole gradients, so each panel keeps its own
     angle (125deg and 145deg; --pathdark is fixed at 135deg). These
     stay deep blue in both themes, which is why the white-alpha
     overlays below are theme-invariant. */
  --deep-1:#0c3156;        /* hero gradient */
  --deep-2:#0864ad;
  --deep-alt-1:#0b2a4a;    /* exam-date gradient */
  --deep-alt-2:#154f7e;
  --on-deep:#ffffff;
  --on-deep-dim:#d7e6f4;   /* 4.8:1 on the LIGHT end of the hero gradient */
  --deep-ring:rgba(255,255,255,.055);
  --deep-track:rgba(255,255,255,.18);
  --chip-warm-bg:rgba(244,123,32,.28);  /* the "Full simulation" chip */
  --chip-warm-ink:#ffe3ce;

  /* Meaningful colour: quiz states, notebook, charts.
     --green/--red are the graphic tone; --*-ink is the same hue pushed
     dark enough to be read as TEXT on its own soft background. */
  --green-line:#74c49e;
  --green-ink:#12704a;     /* 5.6:1 on --green-soft; --green measured 4.2 */
  --on-green:#ffffff;
  --red-soft:#fff0f0;
  --red-line:#e2a1a1;
  --red-ink:#b02c2c;       /* 5.9:1 on --red-soft */
  --on-red:#ffffff;

  /* Violet — the account page's "mastery" accent. The third achievement
     stat has to read as a different thing from the streak (orange) and
     the weekly goal (blue), and no existing token carries a third hue.
     --violet is the TEXT/icon tone, --violet-2 the lighter gradient end. */
  --violet:#7550a8;        /* 5.6:1 on --violet-soft */
  --violet-2:#a879d4;
  --violet-soft:#f1eafb;

  /* Bars and tracks. --track is an EMPTY rail, --bar-idle is a bar that
     carries data but is not today's. They must stay distinguishable. */
  --track:#e4ebf2;
  --bar-idle:#cfe0ef;

  /* Per-unit accent. The ten unit hues come from practice-data.js and are
     fixed, so the theme adjusts them instead: light pushes them toward
     ink (the two oranges measured 2.4:1 raw), dark lifts them toward
     paper. Worst case after mixing is 3.5:1 light, 6.0:1 dark. */
  --unit-ink-mix:78%;
  --unit-ink-base:#16283c;

  /* type — one family, four weights */
  --font:'Poppins',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --w-body:400;
  --w-med:500;
  --w-semi:600;   /* card titles, buttons, labels */
  --w-bold:700;   /* headings and figures. 800 is retired. */

  /* radius — small for controls, large for panels. No pills on wide elements. */
  --r-xs:8px;
  --r-sm:10px;
  --r-md:12px;
  --r-lg:14px;
  --r-pill:99px;  /* only for chips and tags */

  /* elevation — Daylight separates surfaces with hairlines, not shadow */
  --sh-1:none;
  --sh-2:0 8px 26px rgba(14,36,57,.07);
  --sh-3:0 12px 34px rgba(14,36,57,.06);
  --sh-4:0 18px 48px rgba(22,49,77,.09);   /* hero + question card */
  --sh-orange:0 9px 22px rgba(177,73,0,.22);
  --sh-green:0 12px 28px rgba(23,133,87,.22);
  --sh-drawer:20px 0 40px rgba(10,35,60,.15);  /* mobile sidebar */

  /* hero illustration */
  --h-paper:#fff; --h-line:#e9eef4; --h-tint:#f1f7fe; --h-track:#eef2f7;
  --h-glow:#f3f8fd; --h-dot:#e3ebf3;
  --h-ink:#16283c; --h-muted:#95a5b6; --h-accent:#ef6c12; --h-on-accent:#fff;

  /* layout */
  --container:1200px;
  --nav-h:72px;

  /* motion — calm. Was 0.3s everywhere with -10px hovers. */
  --t:.18s ease;
}

/* ---------- 1b. DARK — "Midnight" ----------
   Three surface levels, because on dark a card cannot be separated
   from the page by shadow the way it can on white: the page is
   darkest, cards sit one step up, tints one step above that.
   Accents are lifted and desaturated — #ef6c12 on near-black
   vibrates, and #0a5fb4 fails contrast against it. */
[data-theme="dark"]{
  color-scheme:dark;

  --navy:#f2f7fc;          /* headings are now the LIGHTEST value */
  --blue:#6fb2f0;
  --blue-2:#8cc4f6;
  --sky:#152b41;
  --orange:#f79445;
  --orange-2:#f9b477;
  --orange-fill:#f79445;   /* on dark the bright tone is the fill... */
  --orange-text:#f7a566;   /* ...and a lifted tone is the text */
  --on-orange:#0a1622;     /* dark text on the orange fill, not white */
  --orange-ink:#f7a566;
  --orange-soft:#2a1a0e;
  --ink:#e6eef7;
  --muted:#9db1c5;
  --muted-2:#8199ae;
  --line:#213548;
  --line-2:#18293a;
  --paper:#111f2e;         /* card surface, one step up from the page */
  --bg:#0a1622;            /* page */
  --green:#4cc48d;
  --green-soft:#10301f;
  --red:#ec8b8b;
  /* Thumbnails are opaque screenshots that carry their own background,
     so the letterbox behind them can go dark — light bars read as a
     bright frame around every tile. Checked all 36 for alpha first;
     a transparent PNG here would dissolve into the card. */
  --thumb-bg:#16283a;
  --thumb-fill:linear-gradient(140deg,#182c3f,#132435);
  --surface-2:#16283a;
  --surface-3:#16283a;
  --border-strong:#33506e;
  --border-hover:#3d5f80;
  --nav-ink:#9db1c5;
  --topbar-bg:rgba(10,22,34,.92);
  --menu-bg:rgba(13,26,40,.98);
  --orange-hover:#f9a460;
  --solid-bg:#24405c;
  --solid-ink:#ffffff;
  --solid-hover:#2d4f70;
  --chip-base:#111f2e;     /* mix toward the CARD, not toward white */
  --dot-idle:#2a4058;
  --focus-ring:rgba(111,178,240,.2);
  --pathdark:linear-gradient(135deg,#1b4471,#0f2f52);
  --footer-bg:#07111c;
  --footer-ink:#b6c8da;
  --footer-dim:#93a9bf;
  --footer-base:#7b94ab;
  --footer-rule:rgba(255,255,255,.11);
  --callout-bg:#1e1710;
  --callout-line:#3d2e1c;
  --callout-ico:#3a2611;
  --callout-ink:#c3ac93;
  --code-bg:#3a2c17;
  --page-header-grad:linear-gradient(115deg,#12253a,var(--paper) 62%);
  --page-header-ring:rgba(111,178,240,.05);

  /* The app page is already the darkest surface — no tint to add. */
  --app-bg:#0a1622;

  /* Deep panels keep their blue identity on dark; they just stop being
     the darkest thing on screen. Same stops as --pathdark's dark values
     so the hero and the grade-path panels read as one family. */
  --deep-1:#1b4471;
  --deep-2:#0f2f52;
  --deep-alt-1:#16324e;
  --deep-alt-2:#102841;
  --on-deep:#ffffff;
  --on-deep-dim:#c2d5e8;   /* 6.6:1 on --deep-1 */
  --deep-ring:rgba(255,255,255,.05);
  --deep-track:rgba(255,255,255,.18);
  --chip-warm-bg:rgba(247,148,69,.22);
  --chip-warm-ink:#ffe3ce;

  /* On dark, --green/--red are already the lifted tone, so they ARE the
     ink; what flips is the text that sits ON them. */
  --green-line:#2c6a4d;
  --green-ink:#4cc48d;
  --on-green:#06251a;      /* 7.5:1 — dark text on the bright green fill */
  --red-soft:#2e1618;
  --red-line:#6b3436;
  --red-ink:#ec8b8b;
  --on-red:#2a0f10;        /* 7.4:1 */

  /* Lifted the same way the other accents are — #7550a8 on a near-black
     card is 2.1:1 and unreadable. 7.5:1 on --violet-soft. */
  --violet:#c4a2e8;
  --violet-2:#a879d4;
  --violet-soft:#251a35;

  --track:#22374d;
  --bar-idle:#2f4a68;

  --unit-ink-mix:55%;
  --unit-ink-base:#f2f7fc;

  --sh-1:none;
  --sh-2:0 14px 34px rgba(0,0,0,.44);
  --sh-3:0 22px 54px rgba(0,0,0,.5);
  --sh-4:0 22px 54px rgba(0,0,0,.5);
  --sh-orange:0 9px 22px rgba(0,0,0,.4);
  --sh-green:0 12px 28px rgba(0,0,0,.42);
  --sh-drawer:20px 0 40px rgba(0,0,0,.5);

  --h-paper:#16283a; --h-line:#28405a; --h-tint:rgba(247,148,69,.17);
  --h-track:#22374d; --h-glow:#132a41; --h-dot:#1e344b;
  --h-ink:#eef4fa; --h-muted:#8ba3ba; --h-accent:#f79445; --h-on-accent:#0a1622;
}

/* ---------- 2. RESET ---------- */
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  font-family:var(--font);
  font-weight:var(--w-body);
  font-size:15px;
  line-height:1.6;
  color:var(--ink);
  background:var(--bg);
  min-height:100vh;
  display:flex;
  flex-direction:column;
}
ul{list-style:none}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0}

/* visible keyboard focus — the live site has none */
:focus-visible{outline:2px solid var(--blue);outline-offset:2px;border-radius:4px}

.container{width:min(92%,var(--container));margin-inline:auto}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---------- 3. TYPE SCALE ---------- */
h1,h2,h3,h4{font-weight:var(--w-bold);letter-spacing:-.03em;color:var(--navy);line-height:1.1}
h1{font-size:clamp(28px,3.6vw,40px)}
h2{font-size:clamp(22px,2.4vw,26px);letter-spacing:-.025em}
h3{font-size:16px;font-weight:var(--w-semi);letter-spacing:-.015em;line-height:1.3}
h4{font-size:14px;font-weight:var(--w-semi);letter-spacing:-.01em}

.eyebrow{
  color:var(--orange-text);
  font-size:11px;
  font-weight:var(--w-semi);
  letter-spacing:.13em;
  text-transform:uppercase;
  margin-bottom:8px;
}
.lead{color:var(--muted);font-size:16px;max-width:52ch}
.muted{color:var(--muted)}
.figure{font-weight:var(--w-bold);letter-spacing:-.02em;color:var(--navy)}

/* ---------- 4. TOP BAR ---------- */
.topbar{
  position:sticky;top:0;z-index:40;
  height:var(--nav-h);
  display:flex;align-items:center;
  background:var(--topbar-bg);
  backdrop-filter:blur(16px);
  border-bottom:1px solid var(--line);
}
.topbar .container{display:flex;align-items:center;gap:30px;height:100%}
.brand{display:flex;align-items:center;flex:0 0 auto}
.brand{position:relative}
.brand img{width:auto;height:50px}
/* logo.png is dark-on-transparent and disappears on a dark surface;
   logo-white.png already exists in the repo, so dark mode swaps to it. */
/* The logo swap is keyed off the pair of classes, not off the brand wrapper.
   Every surface names its wrapper differently — .brand, .account-brand,
   .admin-brand, .worksheet-brand, .search-logo, .collections-brand — and
   scoping this per wrapper meant each new one silently showed both logos
   at once until someone noticed.
   The class is doubled to raise specificity: several pages style their brand
   image as `.some-brand img { display: block }`, which is (0,1,1) and loads
   after this file, so a single class would lose and both logos would show. */
.logo-dark.logo-dark{display:none}
[data-theme="dark"] .logo-light.logo-light{display:none}
[data-theme="dark"] .logo-dark.logo-dark{display:block}

/* theme toggle */
.theme-toggle{
  display:grid;place-items:center;
  width:40px;height:40px;flex:0 0 auto;
  border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--muted);background:var(--paper);
  transition:var(--t);
}
.theme-toggle:hover{color:var(--navy);border-color:var(--border-hover);background:var(--surface-2)}
.theme-toggle .i-sun{display:none}
.theme-toggle .i-moon{display:block}
[data-theme="dark"] .theme-toggle .i-sun{display:block}
[data-theme="dark"] .theme-toggle .i-moon{display:none}
.topnav{display:flex;gap:24px;align-self:stretch}
.topnav a{
  display:flex;align-items:center;
  border-bottom:3px solid transparent;
  color:var(--nav-ink);font-size:13.5px;font-weight:var(--w-med);
  transition:var(--t);
}
.topnav a:hover{color:var(--navy)}
.topnav a[aria-current=page]{border-color:var(--orange);color:var(--navy);font-weight:var(--w-semi)}
.nav-right{margin-left:auto;display:flex;align-items:center;gap:8px}
.nav-toggle{display:none;margin-left:auto;padding:8px;border-radius:var(--r-xs);color:var(--navy)}
.nav-toggle svg{display:block}

/* ---------- 5. BUTTONS ----------
   Solid fills only. The old gradient faded to #aabdd6, which
   read as disabled. Radius is 10px, not a 30px pill. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  min-height:46px;padding:0 22px;
  border-radius:var(--r-sm);
  font-size:14.5px;font-weight:var(--w-semi);
  transition:var(--t);
  white-space:nowrap;
}
.btn svg{flex:0 0 auto}

.btn-primary{color:var(--on-orange);background:var(--orange-fill);box-shadow:0 8px 20px rgba(120,50,0,.22)}
.btn-primary:hover{background:var(--orange-hover);transform:translateY(-1px)}

.btn-navy{color:var(--solid-ink);background:var(--solid-bg)}
.btn-navy:hover{background:var(--solid-hover)}

.btn-secondary{border:1px solid var(--border-strong);color:var(--blue);background:var(--paper)}
.btn-secondary:hover{background:var(--sky)}

/* the workhorse: the button inside every resource card */
.btn-card{
  display:flex;align-items:center;justify-content:center;gap:7px;
  width:100%;min-height:38px;
  border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--blue);background:var(--surface-3);
  font-size:13.5px;font-weight:var(--w-semi);
  transition:var(--t);
}
.btn-card:hover{border-color:var(--border-hover);background:var(--sky)}

/* "not yet" now looks unavailable instead of clickable */
.btn-locked{
  display:flex;align-items:center;justify-content:center;gap:7px;
  width:100%;min-height:38px;
  border:1px dashed var(--border-strong);border-radius:var(--r-sm);
  /* --muted-2 is 4.5:1 on white, but this sits on --surface-2, which is a
     shade off white and drops it to 4.38:1. Measured, not eyeballed. */
  color:var(--muted);background:var(--surface-2);
  font-size:13.5px;font-weight:var(--w-semi);
  cursor:not-allowed;
}
.btn-sm{min-height:38px;padding:0 16px;font-size:13.5px}
.btn-text{color:var(--blue);font-size:13.5px;font-weight:var(--w-semi)}
.btn-text:hover{text-decoration:underline}

/* ---------- 6. PAGE HEADER ----------
   Replaces the 40 wordmark banner images. Real text, so it
   translates and search engines can read it. */
.page-header{
  position:relative;overflow:hidden;
  padding:28px 30px;
  border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--page-header-grad);
  margin-bottom:22px;
}
.page-header::after{
  content:"";position:absolute;right:-58px;top:-70px;
  width:220px;height:220px;
  border:44px solid var(--page-header-ring);border-radius:50%;
}
.page-header>*{position:relative}
.page-header .motif{
  display:grid;place-items:center;
  width:46px;height:46px;margin-bottom:14px;
  border-radius:var(--r-md);
  background:var(--sky);color:var(--blue);
}
.page-header .motif.warm{background:var(--orange-soft);color:var(--orange)}
.page-header p{margin-top:9px;color:var(--muted);font-size:14.5px;max-width:50ch}
.stat-row{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap}
.stat-row span{
  padding:6px 12px;
  border:1px solid var(--line);border-radius:var(--r-pill);
  background:var(--paper);
  color:var(--nav-ink);font-size:11.5px;font-weight:var(--w-semi);
}

.breadcrumb{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:var(--muted-2);font-size:12.5px}
.breadcrumb a{color:var(--blue);font-weight:var(--w-med)}
.breadcrumb a:hover{text-decoration:underline}

/* ---------- 7. SECTION HEADING ---------- */
.section-heading{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:22px;margin:34px 0 16px;
}
.section-heading p{margin-top:6px;color:var(--muted);font-size:14px}
.section-heading:first-child{margin-top:0}
/* The admin-published block is a sibling of the theme grid, not the top of a
   container, but its heading is still a :first-child — so the rule above was
   stripping the section air and leaving "Also published…" against the cards.
   The margin goes on the block, which is also what stays hidden when nothing
   has been published. */
#dynamic-themes{margin-top:38px}

/* ---------- 8. CARDS ----------
   1px hairline border + defined shadow. The old card had a
   3%-alpha shadow and a #f1f5f9 border, which read as soft. */
.card{
  border:1px solid var(--line);
  border-radius:var(--r-md);
  background:var(--paper);
  padding:18px;
  transition:var(--t);
}
.card-hover:hover{border-color:var(--border-hover);box-shadow:var(--sh-2);transform:translateY(-2px)}

/* resource card — was 440px tall with a 260px image, now ~150px */
.res-card{display:flex;flex-direction:column}
.res-card-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.chip{
  display:grid;place-items:center;
  width:44px;height:44px;
  border-radius:var(--r-md);
  color:color-mix(in srgb,var(--c,var(--blue)) 82%,#000);
  background:color-mix(in srgb,var(--c,var(--blue)) 12%,var(--chip-base));
}
.chip svg{width:21px;height:21px}
.chip-num{font-size:17px;font-weight:var(--w-bold);letter-spacing:-.02em}
/* The per-card --c values are light-mode hues (a deep blue, a deep
   purple). Used as-is on a dark chip they measure 2.7:1. Lighten the
   glyph and strengthen the tint so the hue survives the theme. */
[data-theme="dark"] .chip{
  color:color-mix(in srgb,var(--c,var(--blue)) 45%,#fff);
  background:color-mix(in srgb,var(--c,var(--blue)) 26%,var(--chip-base));
}
.res-count{color:var(--muted-2);font-size:10px;font-weight:var(--w-semi);letter-spacing:.1em}
.res-card p{margin:3px 0 15px;color:var(--muted);font-size:12.5px;flex:1}

/* grid helpers */
.grid{display:grid;gap:14px}
.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}

/* ---------- 9. PROOF BAND ---------- */
.proof-band{
  display:grid;grid-template-columns:repeat(4,1fr);
  margin:26px 0 8px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);overflow:hidden;
}
.proof-band div{padding:18px 20px;border-right:1px solid var(--line-2)}
.proof-band div:last-child{border-right:0}
.proof-band strong{display:block;font-size:26px;font-weight:var(--w-bold);letter-spacing:-.03em;color:var(--navy);line-height:1.15}
.proof-band span{display:block;margin-top:3px;color:var(--muted-2);font-size:12px}

/* ---------- 10. TAB STRIP (themes) ---------- */
.tab-strip{
  display:flex;gap:6px;
  padding:6px;margin-bottom:22px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);
  overflow-x:auto;scrollbar-width:thin;
}
.tab-strip button{
  flex:0 0 auto;
  padding:9px 16px;border-radius:var(--r-xs);
  color:var(--muted);font-size:13px;font-weight:var(--w-semi);
  white-space:nowrap;transition:var(--t);
}
.tab-strip button:hover{background:var(--surface-2);color:var(--navy)}
.tab-strip button[aria-selected=true]{background:var(--sky);color:var(--blue)}

/* ---------- 11. FILTER BAR ---------- */
.filter-bar{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:13px;margin-bottom:16px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);
}
.filter-bar .flabel{
  color:var(--muted-2);font-size:10.5px;font-weight:var(--w-semi);
  letter-spacing:.1em;text-transform:uppercase;
}
.filter-bar .fgroup{display:flex;gap:6px;flex-wrap:wrap}
.filter-bar button{
  padding:8px 13px;
  border:1px solid var(--line);border-radius:var(--r-xs);
  background:var(--paper);color:var(--muted);
  font-size:12.5px;font-weight:var(--w-semi);
  transition:var(--t);
}
.filter-bar button:hover{border-color:var(--border-hover);color:var(--navy)}
.filter-bar button[aria-pressed=true]{border-color:var(--blue);background:var(--sky);color:var(--blue)}
.search-field{
  margin-left:auto;display:flex;align-items:center;gap:8px;
  padding:0 13px;height:40px;min-width:210px;
  border:1px solid var(--line);border-radius:var(--r-xs);
  background:var(--paper);color:var(--muted-2);
}
.search-field svg{flex:0 0 auto}
.search-field input{border:0;outline:0;background:none;width:100%;font-size:13px;color:var(--ink)}
.result-line{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:14px}
.result-line p{color:var(--muted);font-size:13px}
.result-line strong{color:var(--navy);font-weight:var(--w-semi)}

/* ---------- 12. GAME TILE ----------
   The fix: every thumbnail in the same 16:9 box. The live site
   has thumbs at 5 aspect ratios (4.02 → 1.44) in a fixed box
   with object-fit:cover, which crops titles out of the wide ones. */
.game-tile{
  display:flex;flex-direction:column;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);overflow:hidden;
  transition:var(--t);
}
.game-tile:hover{border-color:var(--border-hover);box-shadow:var(--sh-2);transform:translateY(-2px)}
.game-thumb{
  position:relative;
  aspect-ratio:16/9;
  background:var(--thumb-bg);
  border-bottom:1px solid var(--line-2);
  overflow:hidden;
}
.game-thumb img{
  width:100%;height:100%;
  object-fit:contain;          /* contain, not cover — nothing gets sliced */
  background:var(--thumb-fill);
}
/* A filtered-out tile has to actually disappear. `display:flex` above is an
   author declaration and the UA sheet's `[hidden]{display:none}` is not, so
   author origin wins and `hidden` alone would leave the tile on screen. Same
   reason .faq-a[hidden] is spelled out. */
.game-tile[hidden]{display:none}
.game-badge{
  position:absolute;top:8px;left:8px;
  padding:4px 8px;border-radius:6px;
  background:rgba(11,42,74,.82);color:#fff;
  font-size:9.5px;font-weight:var(--w-semi);letter-spacing:.07em;text-transform:uppercase;
}
.game-body{padding:12px 13px 13px;display:flex;flex-direction:column;flex:1}
.game-body h3{font-size:13.5px;min-height:35px}
.tag-row{display:flex;gap:6px;margin:8px 0 12px;flex-wrap:wrap}
.tag{
  padding:3px 9px;border-radius:var(--r-pill);
  background:var(--surface-2);color:var(--muted);
  font-size:10px;font-weight:var(--w-semi);
}
.tag-grade{background:var(--sky);color:var(--blue)}
.tag-todo{background:var(--orange-soft);color:var(--orange-ink)}
.empty-note{
  padding:50px 20px;text-align:center;
  border:1px dashed var(--line);border-radius:var(--r-md);
  background:var(--paper);color:var(--muted);
}

/* ---------- 13. HERO + PATHS ---------- */
.hero{display:grid;grid-template-columns:1.05fr .95fr;gap:40px;align-items:center;padding:34px 0 6px}
.hero .cta-row{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px}
.hero .micro{margin-top:14px;color:var(--muted-2);font-size:12.5px}
.hero-art{
  border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--paper);padding:12px;box-shadow:var(--sh-3);
}
.hero-art img{border-radius:var(--r-md)}

.path-card{border:1px solid var(--line);border-radius:var(--r-md);background:var(--paper);padding:24px}
.path-card.dark{background:var(--pathdark);border-color:transparent}
.path-card.dark h3,.path-card.dark .path-lbl{color:#fff}
.path-card.dark p,.path-card.dark li{color:#c5d9eb}
.path-lbl{
  display:inline-flex;padding:5px 10px;margin-bottom:12px;
  border-radius:6px;background:var(--sky);color:var(--blue);
  font-size:10px;font-weight:var(--w-semi);letter-spacing:.09em;text-transform:uppercase;
}
.path-card.dark .path-lbl{background:rgba(244,123,32,.22);color:#ffe3ce}
.path-card h3{font-size:19px;font-weight:var(--w-bold);letter-spacing:-.025em;margin-bottom:8px}
.path-card>p{color:var(--muted);font-size:13.5px;margin-bottom:16px}
.path-card ul{margin-bottom:18px}
.path-card li{position:relative;padding:6px 0 6px 22px;color:var(--nav-ink);font-size:13px}
.path-card li::before{content:"";position:absolute;left:0;top:14px;width:9px;height:2px;background:var(--orange);border-radius:2px}

/* ---------- 14. QUOTE ---------- */
.quote-block{
  display:grid;grid-template-columns:1fr auto;gap:26px;align-items:center;
  padding:28px;margin-top:28px;
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--paper);
}
.quote-block blockquote{font-size:19px;line-height:1.45;font-weight:var(--w-med);letter-spacing:-.015em;color:var(--navy)}
.quote-who{display:flex;align-items:center;gap:11px;margin-top:16px}
.quote-who .initials{
  display:grid;place-items:center;width:38px;height:38px;
  border-radius:var(--r-sm);background:var(--sky);color:var(--blue);
  font-size:13px;font-weight:var(--w-semi);
}
.quote-who strong{display:block;font-size:13px;font-weight:var(--w-semi);color:var(--ink)}
.quote-who small{display:block;color:var(--muted-2);font-size:11.5px}
.quote-dots{display:flex;gap:7px}
.quote-dots button{width:9px;height:9px;border-radius:50%;background:var(--dot-idle);transition:var(--t)}
.quote-dots button[aria-current=true]{background:var(--orange)}

/* ---------- 15. FORMS ---------- */
.form-card{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--paper);padding:28px}
.field{margin-bottom:16px}
.field label{display:block;margin-bottom:6px;font-size:12.5px;font-weight:var(--w-semi);color:var(--navy)}
.field label small{color:var(--muted-2);font-weight:var(--w-med)}
.field input,.field textarea{
  width:100%;padding:12px 13px;
  border:1px solid var(--border-strong);border-radius:var(--r-sm);   /* real borders — was a borderless grey fill */
  background:var(--paper);font-size:14px;
  transition:var(--t);
}
.field input:focus,.field textarea:focus{outline:0;border-color:var(--blue);box-shadow:0 0 0 3px var(--focus-ring)}
/* Unstyled placeholders fall back to the UA grey (#757575), which is
   3.6:1 on the dark field — these carry real information, so they get
   a token that passes in both themes. */
.field input::placeholder,.field textarea::placeholder{color:var(--muted-2);opacity:1}
.field textarea{min-height:104px;resize:vertical}
.field-note{margin-top:14px;color:var(--muted-2);font-size:12px}
.field-note a{color:var(--blue);font-weight:var(--w-med)}

.side-card{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--paper);padding:24px;height:max-content}
.side-card>p{color:var(--muted);font-size:13px;margin-bottom:6px}
.side-row{display:grid;grid-template-columns:34px 1fr;gap:12px;padding:14px 0;border-top:1px solid var(--line-2)}
.side-row .ico{display:grid;place-items:center;width:34px;height:34px;border-radius:var(--r-sm);background:var(--sky);color:var(--blue)}
.side-row strong{display:block;font-size:12.5px;font-weight:var(--w-semi);color:var(--ink)}
.side-row small{display:block;margin-top:1px;color:var(--muted-2);font-size:11.5px}

/* ---------- 16. FAQ ----------
   One bordered list. Was seven separate 99px-radius grey pills. */
.faq{margin-top:24px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--paper);overflow:hidden}
.faq-item{border-bottom:1px solid var(--line-2)}
.faq-item:last-child{border-bottom:0}
.faq-q{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 20px;text-align:left;
  font-size:14px;font-weight:var(--w-semi);color:var(--navy);
  transition:var(--t);
}
.faq-q:hover{background:var(--surface-2)}
.faq-q .sign{flex:0 0 auto;color:var(--muted-2);transition:transform var(--t)}
.faq-q[aria-expanded=true]{background:var(--surface-2)}
.faq-q[aria-expanded=true] .sign{transform:rotate(45deg);color:var(--blue)}
.faq-a{padding:0 20px 18px;background:var(--surface-2);color:var(--muted);font-size:13.5px}
.faq-a[hidden]{display:none}

/* ---------- 17. FOOTER ---------- */
.site-footer{margin-top:auto;padding:56px 0 28px;background:var(--footer-bg);color:#fff}
.footer-grid{
  display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:40px;
  padding-bottom:36px;border-bottom:1px solid var(--footer-rule);
}
.footer-grid img{width:190px;margin-bottom:16px}
.footer-grid h4{color:#fff;font-size:12px;font-weight:var(--w-semi);letter-spacing:.1em;text-transform:uppercase;margin-bottom:14px;opacity:.62}
.footer-grid li{margin-bottom:10px}
.footer-grid li a{color:var(--footer-ink);font-size:13.5px;transition:var(--t)}
.footer-grid li a:hover{color:#fff}
.footer-blurb{color:var(--footer-dim);font-size:13px;max-width:34ch}
.social{display:flex;gap:10px;margin-top:16px}
.social a{
  display:grid;place-items:center;width:36px;height:36px;
  border:1px solid rgba(255,255,255,.2);border-radius:var(--r-sm);
  color:#fff;transition:var(--t);
}
.social a:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.4)}
.footer-base{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding-top:22px;color:var(--footer-base);font-size:12px;flex-wrap:wrap;
}

/* ---------- 18. PROTOTYPE-ONLY CHROME ---------- */
.proto-flag{
  position:sticky;top:0;z-index:60;
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:9px 18px;
  background:#0b2a4a;color:#cfe0f0;
  font-size:12px;
}
.proto-flag strong{color:#fff;font-weight:var(--w-semi)}
.proto-flag .spacer{margin-left:auto}
.proto-flag a,.proto-flag button{
  color:#fff;border:1px solid rgba(255,255,255,.28);
  padding:4px 11px;border-radius:6px;font-size:11.5px;font-weight:var(--w-semi);
  transition:var(--t);
}
.proto-flag a:hover,.proto-flag button:hover{background:rgba(255,255,255,.12)}
.proto-flag a[aria-current=page]{background:#f47b20;border-color:#f47b20}
.callout{
  display:grid;grid-template-columns:40px 1fr;gap:14px;
  padding:18px 20px;margin:26px 0 0;
  border:1px solid var(--callout-line);border-radius:var(--r-md);background:var(--callout-bg);
}
.callout .ico{display:grid;place-items:center;width:40px;height:40px;border-radius:var(--r-sm);background:var(--callout-ico);color:var(--orange-ink)}
.callout strong{display:block;font-size:14px;font-weight:var(--w-semi);color:var(--navy);margin-bottom:4px}
.callout p{color:var(--callout-ink);font-size:13.5px}
.callout code{background:var(--code-bg);padding:1px 6px;border-radius:5px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px}

.page{padding:26px 0 60px;flex:1}

/* ---------- 19. RESPONSIVE ---------- */
@media(max-width:1000px){
  .grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .proof-band{grid-template-columns:repeat(2,1fr)}
  .proof-band div:nth-child(2){border-right:0}
  .proof-band div:nth-child(-n+2){border-bottom:1px solid var(--line-2)}
  .footer-grid{grid-template-columns:1fr 1fr}
}
@media(max-width:860px){
  .hero{grid-template-columns:1fr;gap:28px}
  .grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}
  .quote-block{grid-template-columns:1fr}
}
@media(max-width:720px){
  .topnav{
    position:absolute;top:var(--nav-h);left:0;right:0;
    flex-direction:column;gap:0;
    padding:8px 5%;
    background:var(--menu-bg);
    border-bottom:1px solid var(--line);
    box-shadow:0 10px 24px rgba(0,0,0,.06);
    display:none;
  }
  .topnav.is-open{display:flex}
  .topnav a{padding:12px 0;border-bottom:1px solid var(--line-2);border-left:3px solid transparent}
  .topnav a[aria-current=page]{border-bottom-color:var(--line-2);border-left-color:var(--orange);padding-left:10px}
  .nav-toggle{display:block;margin-left:6px}
  /* The whole nav-right cluster used to be hidden here, which took the
     theme toggle with it — and a phone is exactly where dark mode gets
     used. display:contents promotes the children to flex items of the
     bar so the toggle can survive on its own. */
  .nav-right{display:contents}
  .nav-right>:not(.theme-toggle){display:none}
  .theme-toggle{margin-left:auto}
  .grid-2,.grid-3,.grid-4{grid-template-columns:1fr}
  .proof-band{grid-template-columns:1fr}
  .proof-band div{border-right:0;border-bottom:1px solid var(--line-2)}
  .proof-band div:last-child{border-bottom:0}
  .footer-grid{grid-template-columns:1fr;gap:28px}
  .search-field{margin-left:0;width:100%}
  .section-heading{flex-direction:column;align-items:flex-start;gap:10px}
  .page-header{padding:22px 20px}
  /* The hero illustration is a detailed UI mock; below 720px it renders
     small enough that its labels stop being legible. Phone hero is the
     headline and the button. */
  .hero-art{display:none}
}

@media(prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important;scroll-behavior:auto!important}
}

/* ============================================================
   20. CONTENT PAGES
   ------------------------------------------------------------
   Every content page on the live site is one of three shapes.
   Rather than six page designs, these are three patterns:
     A  gallery      — many items you open or download
     B  embed viewer — one Canva/Genially iframe
     C  file detail  — one preview plus a PDF
   ============================================================ */

/* ---- shared toolbar above any content body ---- */
.toolbar{
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;flex-wrap:wrap;margin-bottom:16px;
}
.toolbar .count{color:var(--muted);font-size:13px}
.toolbar .count strong{color:var(--navy);font-weight:var(--w-semi)}
.toolbar .actions{display:flex;gap:8px;flex-wrap:wrap}

/* ---- A. GALLERY ----
   Frame ratio is set per content type via --ratio. Within a type the
   source images are consistently shaped (all three infographics are
   ~1.72), so cover is safe here — unlike the game thumbnails, which
   arrive at five different ratios and have to use contain. */
.gallery{display:grid;gap:14px;grid-template-columns:repeat(3,minmax(0,1fr))}
.gallery.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}

.item-card{
  display:flex;flex-direction:column;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);overflow:hidden;transition:var(--t);
}
.item-card:hover{border-color:var(--border-hover);box-shadow:var(--sh-2);transform:translateY(-2px)}
.item-thumb{
  position:relative;
  aspect-ratio:var(--ratio,16/9);
  background:var(--thumb-bg);
  border-bottom:1px solid var(--line-2);
  overflow:hidden;
}
/* A canvas sits here for the same reason an image does: a worksheet's on-screen
   pages are drawn from the worksheet's own PDF rather than uploaded a second
   time, so the thumbnail is a canvas and has to fill the frame identically. */
.item-thumb img,.item-thumb canvas{width:100%;height:100%;object-fit:cover;object-position:center top;display:block}
.item-thumb.fit img,.item-thumb.fit canvas{object-fit:contain;background:var(--thumb-fill)}
/* the whole thumb is the open affordance */
.item-thumb button{
  position:absolute;inset:0;width:100%;
  display:grid;place-items:center;
  background:transparent;transition:var(--t);
}
.item-thumb button span{
  display:inline-flex;align-items:center;gap:7px;
  padding:8px 14px;border-radius:var(--r-pill);
  background:rgba(8,20,34,.86);color:#fff;
  font-size:12.5px;font-weight:var(--w-semi);
  opacity:0;transform:translateY(4px);transition:var(--t);
}
.item-thumb button:hover{background:rgba(8,20,34,.34)}
.item-thumb button:hover span,.item-thumb button:focus-visible span{opacity:1;transform:none}
.item-num{
  position:absolute;top:8px;left:8px;z-index:1;
  padding:3px 8px;border-radius:6px;
  background:rgba(8,20,34,.8);color:#fff;
  font-size:10px;font-weight:var(--w-semi);letter-spacing:.06em;
}
.item-body{display:flex;flex-direction:column;flex:1;padding:14px}
.item-body h3{margin-bottom:6px}
.item-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.item-meta span{color:var(--muted-2);font-size:11.5px}
.item-meta span+span::before{content:"·";margin-right:8px;color:var(--line)}
.item-actions{display:flex;gap:8px;margin-top:auto}
.item-actions .btn-card{flex:1}
.icon-btn{
  display:grid;place-items:center;
  width:38px;min-height:38px;flex:0 0 auto;
  border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--muted);background:var(--surface-3);transition:var(--t);
}
.icon-btn:hover{border-color:var(--border-hover);color:var(--blue);background:var(--sky)}

/* ---- lightbox: the missing piece.
   Today an infographic's only action is "download" — a student has to
   pull a .webp onto their phone to read it. ---- */
.lightbox{
  position:fixed;inset:0;z-index:100;display:none;
  background:rgba(5,13,22,.93);backdrop-filter:blur(8px);
}
.lightbox.is-open{display:grid;grid-template-rows:auto 1fr auto}
.lb-bar{
  display:flex;align-items:center;gap:16px;
  padding:14px 18px;border-bottom:1px solid rgba(255,255,255,.12);
  color:#fff;
}
.lb-bar strong{font-size:14px;font-weight:var(--w-semi)}
.lb-bar .lb-count{color:#9fb3c6;font-size:12.5px}
.lb-bar .lb-tools{margin-left:auto;display:flex;gap:8px}
.lb-bar .lb-tools a,.lb-bar .lb-tools button{
  display:inline-flex;align-items:center;gap:7px;
  min-height:36px;padding:0 13px;
  border:1px solid rgba(255,255,255,.24);border-radius:var(--r-sm);
  color:#fff;font-size:12.5px;font-weight:var(--w-semi);transition:var(--t);
}
.lb-bar .lb-tools a:hover,.lb-bar .lb-tools button:hover{background:rgba(255,255,255,.13)}
.lb-stage{display:grid;place-items:center;padding:20px;overflow:auto}
.lb-stage img{max-width:min(1180px,94vw);max-height:100%;border-radius:var(--r-sm);background:#fff;cursor:zoom-in}
/* Zoomed: drop the fit cap and let the stage scroll, so the small print on
   an infographic can be read at its own size instead of squeezed to fit. */
.lb-stage.is-zoomed{place-items:start}
.lb-stage.is-zoomed img{max-width:none;max-height:none;cursor:zoom-out}
/* Faint pulse while the original is on its way from the CDN. The thumbnail
   is already showing, so this only signals that a sharper one is coming. */
.lightbox.is-loading .lb-stage img{animation:lb-wait 1.1s ease-in-out infinite}
@keyframes lb-wait{50%{opacity:.72}}
@media(prefers-reduced-motion:reduce){
  .lightbox.is-loading .lb-stage img{animation:none;opacity:.85}
}
.lb-foot{display:flex;align-items:center;justify-content:center;gap:10px;padding:14px}
.lb-foot button{
  display:inline-flex;align-items:center;gap:8px;
  min-height:40px;padding:0 16px;
  border:1px solid rgba(255,255,255,.24);border-radius:var(--r-sm);
  color:#fff;font-size:13px;font-weight:var(--w-semi);transition:var(--t);
}
.lb-foot button:hover:not(:disabled){background:rgba(255,255,255,.13)}
.lb-foot button:disabled{opacity:.32;cursor:not-allowed}

/* ---- B. EMBED VIEWER ----
   Click-to-load: the poster is ours, the iframe is only created when
   the student asks for it. Nothing reaches Canva or Genially on page
   load, and the page stops costing a third-party request per visit. */
.embed-frame{
  position:relative;
  aspect-ratio:16/9;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--thumb-bg);overflow:hidden;
}
.embed-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.embed-poster{position:absolute;inset:0;width:100%;padding:0;border:0;background:none;cursor:pointer}
.embed-poster img{width:100%;height:100%;object-fit:cover;display:block}
/* The poster is a real slide, so it already has type on it. The scrim
   has to be strong enough that our label wins, and the label sits on
   its own plate rather than floating over the artwork. */
.embed-poster::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(60% 60% at 50% 50%,rgba(5,14,24,.72),rgba(5,14,24,.42) 70%,rgba(5,14,24,.5));
  transition:var(--t);
}
.embed-poster:hover::after{
  background:radial-gradient(60% 60% at 50% 50%,rgba(5,14,24,.8),rgba(5,14,24,.5) 70%,rgba(5,14,24,.58));
}
.embed-play{
  position:absolute;inset:0;z-index:1;
  display:grid;place-items:center;align-content:center;gap:14px;
  color:#fff;pointer-events:none;text-align:center;
}
.embed-play i{
  display:grid;place-items:center;width:64px;height:64px;
  border-radius:50%;background:var(--orange);color:var(--on-orange);
  box-shadow:0 12px 30px rgba(0,0,0,.42);
}
.embed-play .label{
  display:grid;gap:2px;
  padding:9px 16px;border-radius:var(--r-sm);
  background:rgba(5,14,24,.78);
  backdrop-filter:blur(3px);
}
.embed-play strong{font-size:15px;font-weight:var(--w-semi)}
.embed-play small{color:#cfe0ee;font-size:12px}
.embed-note{
  display:flex;align-items:center;gap:9px;
  margin-top:10px;color:var(--muted-2);font-size:12px;
}

/* ---- C. FILE DETAIL ---- */
.file-layout{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(260px,.85fr);gap:16px;align-items:start}
.file-preview{
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--thumb-bg);overflow:hidden;
}
.file-preview img{width:100%;display:block}
.file-about{
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);padding:22px;
}
.file-about h3{margin-bottom:4px}
.file-about>p{color:var(--muted);font-size:13px;margin-bottom:18px}
.file-facts{margin-bottom:18px}
.file-facts div{
  display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:10px 0;border-top:1px solid var(--line-2);font-size:13px;
}
.file-facts div:last-child{border-bottom:1px solid var(--line-2)}
.file-facts dt{color:var(--muted)}
.file-facts dd{color:var(--ink);font-weight:var(--w-semi);text-align:right}
.file-about .btn{width:100%}
/* Open and Download share a row. Both buttons are full-width on their own,
   so the row overrides that; the 140px basis lets them stack rather than
   squeeze the labels once the panel gets narrow. */
.file-actions{display:flex;flex-wrap:wrap;gap:10px}
.file-actions .btn{flex:1 1 140px;width:auto}
.file-hint{margin-top:12px;color:var(--muted-2);font-size:12px}
/* a 15 MB PDF on a phone plan deserves a warning, not a surprise */
.size-flag{
  display:inline-flex;align-items:center;gap:6px;
  padding:3px 9px;border-radius:var(--r-pill);
  background:var(--orange-soft);color:var(--orange-ink);
  font-size:11px;font-weight:var(--w-semi);
}

/* ---- pager: move within a theme without going back up ---- */
.pager{
  display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:26px;
}
.pager a{
  display:flex;align-items:center;gap:12px;
  padding:16px 18px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);transition:var(--t);
}
.pager a:hover{border-color:var(--border-hover);background:var(--surface-2)}
.pager a.next{justify-content:flex-end;text-align:right}
.pager small{display:block;color:var(--muted-2);font-size:11px;margin-bottom:2px}
.pager strong{display:block;color:var(--navy);font-size:14px;font-weight:var(--w-semi)}
.pager svg{flex:0 0 auto;color:var(--muted)}

/* ---- EXTRAS: wide collection rows ---- */
.collection{display:grid;gap:12px}
.collection-card{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;gap:22px;
  padding:22px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);transition:var(--t);
}
.collection-card:hover{border-color:var(--border-hover);box-shadow:var(--sh-2);transform:translateY(-2px)}
.collection-card .chip{width:52px;height:52px}
.collection-card h3{font-size:17px;font-weight:var(--w-bold);letter-spacing:-.02em;margin-bottom:4px}
.collection-card p{color:var(--muted);font-size:13.5px;max-width:58ch}
.collection-card .tag-row{margin:10px 0 0}
.collection-card .go{
  display:grid;place-items:center;width:40px;height:40px;
  border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--blue);background:var(--surface-3);transition:var(--t);
}
.collection-card:hover .go{background:var(--sky);border-color:var(--border-hover)}

@media(max-width:1000px){
  .gallery{grid-template-columns:repeat(2,minmax(0,1fr))}
  .file-layout{grid-template-columns:1fr}
}
@media(max-width:720px){
  .gallery,.gallery.cols-2{grid-template-columns:1fr}
  .pager{grid-template-columns:1fr}
  .collection-card{grid-template-columns:auto minmax(0,1fr);gap:16px}
  .collection-card .go{display:none}
  .lb-bar{flex-wrap:wrap;gap:10px}
  .lb-bar .lb-tools{margin-left:0;width:100%}
}

/* ============================================================
   21. GRADE PAGES
   ------------------------------------------------------------
   A grade page is one document holding every resource view, and
   only one is visible at a time. That part is unchanged — what
   changed is how you move between them: ordinary #view- links,
   handled by assets/grade-view.js.
   ============================================================ */
.view-section{display:none}
.view-section.active{display:block}

/* The poster gate in front of a third-party embed. The iframe is
   in the markup with data-src and stays cold until the poster is
   pressed; assets/lazy-embeds.js does the loading. */
.embed-frame.is-live>.embed-poster,
.embed-frame.is-live>.embed-play{display:none}

/* An unavailable resource is stated, not hidden: an empty theme
   card reads as a bug, and a missing worksheet is not one. */
.res-card .btn-locked{margin-top:auto}
.empty-note a{color:var(--blue);font-weight:var(--w-med)}
.empty-note a:hover{text-decoration:underline}

/* ---- cards rendered by JavaScript ----
   assets/worksheet-catalog.js and the admin-materials module build
   the old .content-card markup, and they are shared with the grade
   pages that have not been converted yet — so their classes cannot
   move. These rules give that markup the current card design
   instead of rewriting three files at once. */
.content-card{
  display:flex;flex-direction:column;
  padding:14px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);transition:var(--t);
}
/* A filtered-out worksheet has to actually disappear. `display:flex` above is
   an author declaration and the UA sheet's `[hidden]{display:none}` is not, so
   author origin wins and `hidden` alone would leave the card on screen — the
   same reason .game-tile[hidden] is spelled out. */
.content-card[hidden]{display:none}
.content-card:hover{border-color:var(--border-hover);box-shadow:var(--sh-2);transform:translateY(-2px)}
.content-card>img{
  width:100%;aspect-ratio:900/750;object-fit:cover;object-position:center top;
  margin-bottom:12px;
  border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--thumb-bg);
}
/* The ratio above is the worksheet scan (~1.2, and 900/750 is the shape the
   six on extras.html arrive in). A video activity or interactive course cover
   is a 16:9 Genially screenshot, and cropping 1.78 into 1.2 with `cover`
   slices a third of it off the sides — the same mistake the game thumbnails
   were making. Those covers get their own ratio instead. */
.content-card.wide-cover>img{aspect-ratio:16/9}
/* assets/worksheet-catalog.css hardcodes a light gradient and #054a91 text,
   and it loads after this file, so dark mode has to out-specify it rather
   than edit a stylesheet four other pages still depend on. */
[data-theme="dark"] .native-worksheet-cover{
  background:var(--thumb-fill);border-color:var(--line);
}
[data-theme="dark"] .native-worksheet-cover span{color:var(--navy)}
[data-theme="dark"] .native-worksheet-cover small{color:var(--orange-text)}
.content-card .card-title-blue{
  margin-bottom:6px;
  color:var(--navy);font-size:16px;font-weight:var(--w-semi);
  letter-spacing:-.015em;line-height:1.3;
}
.content-card .card-title-orange{margin-bottom:10px;color:var(--muted-2);font-size:11.5px}
.content-card .card-text{margin-bottom:10px;color:var(--muted);font-size:12.5px}
.content-card .btn-view,.content-card .btn-download{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  margin-top:auto;min-height:38px;padding:0 14px;
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--surface-3);
  color:var(--blue);font-size:13px;font-weight:var(--w-semi);
  transition:var(--t);
}
.content-card .btn-view:hover,.content-card .btn-download:hover{
  border-color:var(--border-hover);background:var(--sky);
}

/* ============================================================
   22. ABOUT · CONTACT · PRIVACY
   ------------------------------------------------------------
   The three pages that are mostly words. They share the chrome
   and the page header with everything else; what they need on
   top of that is a readable measure and, for the privacy
   notice, a two-column reading layout.
   ============================================================ */

/* ---- prose ----
   66ch, because a paragraph set across a 1200px container is
   ~160 characters a line and the eye loses its place. The old
   About page centred four paragraphs in orange; this is the
   same words, left-aligned, in body ink. */
/* ---- About story ----
   The story used to sit beside a stock photograph. Without it a
   66ch measure left the right half of a 1200px container empty,
   so the heading moves into its own column instead: the text keeps
   a readable line length and the row fills the width without
   needing an image back. Stacks below 860px. */
.story-grid{
  display:grid;
  grid-template-columns:minmax(200px,280px) minmax(0,72ch);
  justify-content:space-between;
  gap:20px 56px;
  align-items:start;
  margin:34px 0 16px;
}
/* Sits against the middle of the text rather than stranded at the top.
   The left edge stays put so it still lines up with the other section
   headings and the hero card. */
.story-grid .section-heading{display:block;margin:0;align-self:center}
/* Fills its column so the text ends flush with the hero card and the
   reason cards above and below; the column itself caps the measure. */
.story-grid .prose{max-width:none}
.prose{max-width:66ch}
.prose p{margin-bottom:16px;color:var(--ink);opacity:.88}
.prose p:last-child{margin-bottom:0}
@media(max-width:860px){
  .story-grid{grid-template-columns:1fr;gap:16px}
}

/* ---- numbered reasons (About) ----
   Was a six-item arrow list beside a stock photograph. Each
   item is one problem and one answer, so it gets two lines:
   the claim in heading ink, the response in muted. */
.reasons{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:20px}
.reason{
  display:grid;grid-template-columns:30px 1fr;gap:13px;
  padding:17px 18px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--paper);
}
.reason .num{
  display:grid;place-items:center;width:30px;height:30px;
  border-radius:var(--r-xs);
  background:var(--sky);color:var(--blue);
  font-size:12px;font-weight:var(--w-semi);
}
.reason strong{
  display:block;margin-bottom:3px;
  color:var(--navy);font-size:13.5px;font-weight:var(--w-semi);letter-spacing:-.01em;
}
.reason span{display:block;color:var(--muted);font-size:13px;line-height:1.5}

/* ---- closing band ---- */
.band{
  padding:26px 30px;margin-top:30px;
  border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--pathdark);color:#fff;
}
.band h2{color:#fff}
.band p{max-width:56ch;margin-top:9px;color:#c5d9eb;font-size:14.5px}
.band .cta-row{display:flex;gap:10px;margin-top:20px;flex-wrap:wrap}

/* ---- contact ----
   Two columns: the form was 460px wide alone in a 1400px page,
   which read as an unfinished screen. */
.contact-grid{display:grid;grid-template-columns:1.35fr .8fr;gap:14px}
/* Netlify swaps this container for the reCAPTCHA widget during deploy
   post-processing, so nothing here can assume a fixed size. */
.form-captcha{display:flex;margin-bottom:18px}

/* An address in the side card is a link, so it has to look like one. */
.side-row strong a{color:var(--blue);overflow-wrap:anywhere}
.side-row strong a:hover{text-decoration:underline}

/* an answer with structure inside it, not just a sentence */
.faq-a p{color:var(--muted);font-size:13.5px}
.faq-a ul{margin:10px 0 0 2px}
.faq-a li{position:relative;padding:4px 0 4px 18px}
.faq-a li::before{
  content:"";position:absolute;left:0;top:12px;
  width:7px;height:2px;border-radius:2px;background:var(--blue);
}

/* ---- the privacy notice ----
   A long legal document, so it keeps its sticky contents list
   and its own narrower measure. The wording is untouched; only
   the colours and the chrome around it are shared now. */
.legal-layout{display:grid;grid-template-columns:242px minmax(0,1fr);gap:44px;margin-top:26px}
.legal-toc{
  position:sticky;top:calc(var(--nav-h) + 16px);align-self:start;
  padding:20px;
  border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--sky);
}
.legal-toc strong{display:block;margin-bottom:12px;color:var(--navy);font-size:12px;font-weight:var(--w-semi)}
.legal-toc a{display:block;padding:7px 0;color:var(--muted);font-size:12.5px;font-weight:var(--w-med)}
.legal-toc a:hover{color:var(--blue);text-decoration:underline}

/* Out-specifies .page-header p, which is 14.5px at 50ch. */
.page-header p.legal-revised{margin-top:12px;max-width:62ch;color:var(--muted-2);font-size:12px;line-height:1.55}

.legal-body{max-width:74ch}
/* the five one-line promises above the notice itself. It is also the
   target of the first contents link, so it needs the same clearance
   below the sticky top bar that a <section> gets. */
.legal-summary{margin-bottom:32px;scroll-margin-top:calc(var(--nav-h) + 18px)}
.legal-summary .card{background:var(--sky)}
/* Out-specifies .legal-body strong further down. */
.legal-body .legal-summary strong{display:block;margin-bottom:5px;color:var(--navy);font-size:13.5px;font-weight:var(--w-semi)}
.legal-summary span{display:block;color:var(--muted);font-size:12.5px;line-height:1.55}
/* The top bar is sticky, so an anchor jump has to stop below it. */
.legal-body section{
  padding-bottom:30px;margin-bottom:30px;
  border-bottom:1px solid var(--line);
  scroll-margin-top:calc(var(--nav-h) + 18px);
}
.legal-body section:last-child{border-bottom:0;margin-bottom:0}
.legal-body h2{margin-bottom:14px}
.legal-body h3{margin:22px 0 8px}
.legal-body p,.legal-body li{color:var(--muted);font-size:14px;line-height:1.75}
.legal-body p{margin-bottom:12px}
.legal-body ul{margin:10px 0 14px;padding-left:20px;list-style:disc}
.legal-body li{margin-bottom:7px}
.legal-body li::marker{color:var(--border-strong)}
.legal-body a{color:var(--blue);font-weight:var(--w-med)}
.legal-body a:hover{text-decoration:underline}
.legal-body strong{color:var(--ink);font-weight:var(--w-semi)}
/* Not .callout: that component is a 40px icon column plus text, and these
   notes are a single paragraph the law puts weight on. */
.legal-note{
  margin:16px 0;padding:16px 18px;
  border:1px solid var(--callout-line);border-left:4px solid var(--orange);
  border-radius:var(--r-sm);
  background:var(--callout-bg);
}
.legal-note p{margin-bottom:0;color:var(--callout-ink)}

@media(max-width:960px){
  .legal-layout{grid-template-columns:1fr;gap:0}
  .legal-toc{position:static;margin-bottom:28px}
}
@media(max-width:860px){
  .contact-grid{grid-template-columns:1fr}
}
@media(max-width:720px){
  .reasons{grid-template-columns:1fr}
  .band{padding:22px 20px}
}
