/* ============================================================
   Shared design tokens + shell styles for all 13 lessons.
   The token system is deliberately small — commit to it.
   ============================================================ */

/* Host Grotesk, self-hosted. Google's CDN is deliberately NOT used: this site
   has to render identically with the wifi off, and its CSP sets font-src 'self'.
   One variable file per subset covers the whole 300-800 weight axis, so every
   title weight comes from these two files. SIL Open Font License; the text is
   in fonts/OFL.txt. To update, replace the woff2 files and change nothing else. */
@font-face {
  font-family: "Host Grotesk";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/host-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Host Grotesk";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/host-grotesk-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Named colors — the whole palette. "Press" is the working ink:
     it fills the probability bars and marks anything interactive. */
  --paper:  #edeff2;   /* page ground — cool ledger gray */
  --card:   #f9fafb;   /* raised surfaces */
  --ink:    #171a21;   /* primary text */
  --mute:   #57606e;   /* secondary text, remainder hatching */
  --rule:   #c6ccd5;   /* hairlines, borders, ticks */
  --press:  #2440c8;   /* working ink blue. RESERVED: a solid press fill means
                          "this is clickable". Never fill static content with it. */

  /* TWO FAMILIES, AND ONLY TWO.
     Host Grotesk carries everything a person reads: titles, prose, buttons,
     labels, chrome.
     Mono is reserved for the model's view of text — tokens, id numbers,
     probabilities, raw prompts and raw model output. That restraint is what
     makes the token chips dissolving into prose in lesson 01 mean something.
     If it is not what the machine sees, it is not mono. */
  --font-sans:    "Host Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono:    ui-monospace, "SF Mono", SFMono-Regular, Menlo, "Cascadia Mono", Consolas, monospace;

  /* kept as names for intent; both resolve to the one sans */
  --font-display: var(--font-sans);
  --font-body:    var(--font-sans);

  /* Title weights. Host Grotesk runs 300-800, but 800 shouts, so titles sit
     below it. Light type on a solid fill optically gains weight, which is why
     --w-invert steps down from --w-head at the same size. Change these four
     numbers to retune the whole site's typographic volume. */
  --w-title:  680;   /* page titles: the wordmark, each lesson name */
  --w-head:   620;   /* section headings, chrome */
  --w-lede:   540;   /* hooks and taglines */
  --w-invert: 580;   /* headings and labels sitting on a solid colour */

  --radius: 8px;
}

/* Learner reads at book size; presenter projects at roughly 2x.
   Everything downstream is in rem, so this one switch does the scaling. */
html { font-size: 17px; }
html[data-mode="presenter"] { font-size: 25px; }

* { box-sizing: border-box; margin: 0; padding: 0; }

/* author display rules (flex/grid) must never defeat the hidden attribute */
[hidden] { display: none !important; }

html {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.5;
  /* iOS inflates text in landscape unless this is pinned */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  /* dvh tracks Safari's collapsing toolbar; vh is the fallback for old browsers */
  min-height: 100vh;
  min-height: 100dvh;
  /* faint engineering-ledger grid */
  background-image:
    linear-gradient(rgba(23, 26, 33, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(23, 26, 33, 0.035) 1px, transparent 1px);
  background-size: 2rem 2rem;
}

a { color: var(--press); }

button { font: inherit; color: inherit; }

kbd {
  font-family: var(--font-mono);
  font-size: 0.78em;
  border: 1px solid var(--rule);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--card);
  padding: 0.05em 0.4em;
  color: var(--mute);
  white-space: nowrap;
}

:focus-visible {
  outline: 3px solid var(--press);
  outline-offset: 2px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---- Site chrome (hidden entirely in presenter mode) ---- */

.chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.8rem 1.4rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.92rem;
}

.chrome.foot {
  border-bottom: 0;
  border-top: 1px solid var(--rule);
  color: var(--mute);
  margin-top: 3rem;
}

.chrome .site-name {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: var(--w-head);
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}

.chrome .site-name:hover { color: var(--press); }

.site-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  color: #fff;
  background: var(--press);
  border-radius: 6px;
}
.site-mark svg { width: 70%; height: 70%; }

.chrome-actions { display: flex; gap: 0.6rem; align-items: center; }

.ghost-btn {
  border: 1px solid var(--rule);
  background: var(--card);
  border-radius: 6px;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  color: var(--mute);
}
.ghost-btn:hover { border-color: var(--press); color: var(--press); }

html[data-mode="presenter"] .chrome { display: none; }
html[data-mode="presenter"] .learner-only { display: none !important; }

/* The takeaway is read aloud by the presenter, never projected. Hiding it
   here (not just via the `hidden` attribute) means toggling into presenter
   mid-session can never leave it on screen. */
html[data-mode="presenter"] .takeaway { display: none !important; }

/* the escape hatch: quiet, always on screen in presenter mode */
.presenter-exit {
  display: none;
  position: fixed;
  right: 0.7rem;
  bottom: 0.7rem;
  z-index: 90;
  font-size: 0.6rem;
  font-family: var(--font-body);
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--card);
  color: var(--mute);
  padding: 0.25rem 0.55rem;
  cursor: pointer;
  opacity: 0.5;
}
.presenter-exit:hover, .presenter-exit:focus-visible { opacity: 1; border-color: var(--press); color: var(--press); }
html[data-mode="presenter"] .presenter-exit { display: inline-flex; align-items: center; gap: 0.35em; }

/* ---- lesson icons (filled by shared/icons.js) ---- */

.mod-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.3rem;
  height: 2.3rem;
  flex: none;
  color: var(--press);
  background: #e6eafc;
  border: 1px solid var(--press);
  border-radius: 9px;
  box-shadow: 0 2px 0 rgba(36, 64, 200, 0.25);
}
.mod-ico svg { width: 68%; height: 68%; }
.mod-ico.sm {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 6px;
  box-shadow: none;
}

.mod-head-top {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.5rem;
}
.mod-head-top .eyebrow { margin-bottom: 0; }

/* the hook: the fun one-liner, demoted to a subtitle under the lesson name */
.hook {
  margin-top: 0.45rem;
  padding-left: 0.75rem;
  border-left: 3px solid var(--press);
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: var(--w-lede);
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--ink);
  max-width: 46ch;
}

/* presenter mode keeps the name + hook but compacts the whole header block */
html[data-mode="presenter"] .hook { font-size: 1rem; margin-top: 0.25rem; padding-left: 0.55rem; }
html[data-mode="presenter"] .mod-ico { width: 1.7rem; height: 1.7rem; border-radius: 7px; box-shadow: none; }
html[data-mode="presenter"] .mod-head-top { margin-bottom: 0.2rem; gap: 0.5rem; }

@media (max-width: 680px) {
  .hook { font-size: 1.05rem; }
}

/* ============================================================
   COLOUR CONTRACT
   solid --press fill + a hard bottom shadow  = you can click it
   --press outline / text / bars / small tiles = accent, not a control
   ============================================================ */

/* every solid-blue control gets the same pressable treatment */
.start-btn,
.lesson-nav .nav-next,
.btn:not(.ghost),
.big-btn:not(.ghost) {
  box-shadow: 0 3px 0 rgba(23, 26, 33, 0.28);
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}
.start-btn:active,
.lesson-nav .nav-next:active,
.btn:not(.ghost):active,
.big-btn:not(.ghost):active {
  transform: translateY(2px);
  box-shadow: 0 1px 0 rgba(23, 26, 33, 0.28);
}

/* ---- lesson-to-lesson navigation (built by shell.js) ---- */

.lesson-nav {
  display: flex;
  align-items: stretch;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-top: 1.6rem;
}

.lesson-nav .nav-prev {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 0 1 auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  padding: 0.6rem 0.9rem;
  text-decoration: none;
  color: var(--mute);
  font-size: 0.9rem;
}
.lesson-nav .nav-prev:hover { border-color: var(--press); color: var(--press); }
.lesson-nav .nav-dir {
  display: block;
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.75;
}

/* the highest-intent moment on the page: make it the loudest control */
.lesson-nav .nav-next {
  display: flex;
  flex-direction: column;
  flex: 1 1 20rem;
  border: 1px solid var(--press);
  border-radius: var(--radius);
  background: var(--press);
  color: #fff;
  padding: 0.7rem 1rem;
  text-decoration: none;
  box-shadow: 0 3px 0 rgba(36, 64, 200, 0.35);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.lesson-nav .nav-next:hover {
  filter: brightness(1.1);
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(36, 64, 200, 0.3);
}
.lesson-nav .nav-kicker {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #cdd6f2;
}
.lesson-nav .nav-title {
  font-family: var(--font-display);
  font-weight: var(--w-invert);
  font-size: 1.2rem;
  letter-spacing: -0.015em;
  line-height: 1.2;
}
.lesson-nav .nav-sub { font-size: 0.88rem; color: #dfe5f7; margin-top: 0.1rem; }

/* ticks in the lesson map for finished lessons */
.map-list li.done > .tick, .map-list a .tick { color: var(--press); font-weight: 700; }
.map-list .tick { width: 1em; display: inline-block; }

/* The closer used to be two stacked panels — a white "what you just saw" and a
   black-and-yellow "why should you care" — which was both twice the reading and
   the loudest thing on the page. It is now one quiet block: the mechanism, then
   what it means for the reader. Styling lives with .takeaway above. */

/* ---- Lesson map overlay (opens on M, built by shell.js) ---- */

.map-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(23, 26, 33, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.map-overlay[hidden] { display: none; }

.map-panel {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 20px 60px rgba(23, 26, 33, 0.25);
  padding: 1.4rem 1.6rem;
  max-width: 34rem;
  width: 100%;
  max-height: 90vh;
  overflow: auto;
  font-size: 0.85rem;
}

.map-panel h2 {
  font-family: var(--font-display);
  font-weight: var(--w-head);
  font-size: 1.1rem;
  margin-bottom: 0.8rem;
}

.map-list {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.35rem 1.2rem;
  margin-bottom: 1rem;
}
.map-list li, .map-list a {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  text-decoration: none;
}
.map-list a:hover { text-decoration: underline; }

.map-list .num {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  color: var(--mute);
  margin-right: 0.5em;
}

.map-list .soon { color: var(--mute); }

.map-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--rule);
  padding-top: 0.8rem;
  color: var(--mute);
}

@media (max-width: 640px) {
  .map-list { grid-template-columns: 1fr; }
}

/* ---- phone adjustments ---- */

@media (max-width: 560px) {
  /* the full app name wraps to four lines beside the mark and crushes the
     buttons, so on a phone the mark carries the branding by itself */
  .chrome .site-name .site-label { display: none; }
  .chrome { padding: 0.6rem 0.9rem; gap: 0.6rem; }
  .chrome-actions { gap: 0.4rem; }
  .ghost-btn { padding: 0.3rem 0.55rem; font-size: 0.85rem; }

  /* keyboard hints are noise on a device without a keyboard */
  .kbd-hints { display: none; }
  .chrome.foot { justify-content: center; text-align: center; }
}

/* ============================================================
   TOUCH DEVICES (phones, iPad)
   Apple's minimum comfortable target is 44x44pt, hover does not
   exist, and Safari keeps :hover stuck on whatever you tapped last.
   ============================================================ */

@media (hover: none) and (pointer: coarse) {
  .kbd-hints { display: none; }
  .chrome.foot { justify-content: center; text-align: center; }

  /* no 300ms double-tap delay, no grey flash on tap */
  a, button, [role="button"], input, label, .cand, .seg-btn, .word {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
  }

  /* everything you can press gets a thumb-sized target */
  .seg-btn { min-height: 44px; padding-block: 0.55rem; }
  .ghost-btn { min-height: 44px; padding-block: 0.5rem; }
  .btn, .big-btn, .start-btn, .nav-prev { min-height: 44px; }
  .detents button { min-height: 44px; padding-block: 0.5rem; }
  .progress-line button { min-height: 44px; display: inline-block; }
  input[type="range"] { height: 44px; }

  /* the site mark alone is a 26px target; give the whole name room */
  .chrome .site-name { min-height: 44px; }
}

/* Sticky-hover guard: only paint hover states where hovering is real.
   Without this, a tapped card on iOS keeps its lifted state until you
   tap somewhere else, which reads as a stuck UI. */
@media (hover: hover) and (pointer: fine) {
  .lesson-nav .nav-next:hover { filter: brightness(1.1); transform: translateY(-2px); }
  .lesson-nav .nav-prev:hover { border-color: var(--press); color: var(--press); }
}
@media (hover: none) {
  .lesson-nav .nav-next:hover,
  .lesson-nav .nav-prev:hover { transform: none; filter: none; }
}

/* Horizontal scrollers must not hand the gesture to Safari's swipe-back. */
.hero-tokens, .map-scroll, .rt-table-wrap {
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}

/* Respect the notch and the home indicator when the page runs edge to edge. */
.chrome { padding-left: max(1.4rem, env(safe-area-inset-left)); padding-right: max(1.4rem, env(safe-area-inset-right)); }
.chrome.foot { padding-bottom: max(0.8rem, env(safe-area-inset-bottom)); }
.presenter-exit {
  right: max(0.7rem, env(safe-area-inset-right));
  bottom: max(0.7rem, env(safe-area-inset-bottom));
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
