/* ============================================================
   Code with AI — per-tab layout & motion
   ------------------------------------------------------------
   Structure and tokens are inherited from make/localai; this file
   keeps only the pieces this site actually uses: the hero, the
   scroll story beats, the tab-card grid, and the glossary.
   All colors via tokens; no hardcoded theme values here.
   ============================================================ */

/* ---------- Hero (full viewport, §6 Tab 1) ------------------- */
.home-hero {
  position: relative;
  overflow: hidden; /* clip the floating panels at the edges */
  /* Was a full viewport. Trimmed 2026-09-05 with the marquee removal so the
     first story beat sits just under the fold instead of a screen below it. */
  min-height: calc(82vh - 56px);
  min-height: calc(82svh - 56px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero-inner {
  position: relative;
  z-index: 1;
  /* Sized so the content column matches the width of the h1 on one line
     (48px type, ~651px). The description then spans exactly the same
     measure as the title above it (owner request, 2026-09-05). */
  max-width: 700px;
  padding: var(--sp-7) var(--sp-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  text-align: center;
}

.hero-inner .eyebrow {
  margin: 0;
  font-size: var(--fs-1);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.hero-inner h1 {
  margin: 0;
  font-size: var(--fs-7);
  line-height: 1.06;
  letter-spacing: -0.02em;
}

.hero-sub {
  margin: 0;
  /* No narrower measure than the title: the description spans the same
     width as the h1 above it (owner request, 2026-09-05). */
  max-width: none;
  font-size: var(--fs-3);
  line-height: 1.6;
  color: var(--text-secondary);
}

.hero-cta { display: flex; gap: var(--sp-3); flex-wrap: wrap; justify-content: center; }

/* Floating glass panels — decorative only (aria-hidden in markup).
   Agent-decided: animate the individual `translate` property so it can't
   clash with any transform on the element; hidden below 900 px. */
.hero-float {
  position: absolute;
  z-index: 0;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-1);
  color: var(--text-secondary);
  white-space: nowrap;
}

.hero-float b { color: var(--text-primary); font-weight: 700; }

.hero-float--a { top: 16%; left: 7%;  animation: float-a 9s  var(--ease-toggle) infinite alternate; }
.hero-float--b { top: 24%; right: 6%; animation: float-b 11s var(--ease-toggle) infinite alternate; }
.hero-float--c { bottom: 18%; left: 13%; animation: float-c 13s var(--ease-toggle) infinite alternate; }

@keyframes float-a { from { translate: 0 0; } to { translate: 0 -20px; } }
@keyframes float-b { from { translate: 0 0; } to { translate: 0 16px; } }
@keyframes float-c { from { translate: 0 0; } to { translate: 0 -14px; } }

@media (max-width: 900px) { .hero-float { display: none; } }

/* Comparison table (P7 M2). Five columns will not fit a narrow screen, so the
   TABLE scrolls inside its own box rather than the page scrolling sideways. */
.table-scroll { overflow-x: auto; margin-top: var(--sp-4); }
.table-scroll table.data { min-width: 720px; }
.table-scroll table.data th[scope="row"] { text-align: left; font-weight: 600; color: var(--text-primary); }
.table-scroll table.data td { vertical-align: top; }
/* ---------- Scroll story (§6 Tab 1: beats) -------------------- */
.home-story {
  max-width: 920px;
  margin-inline: auto;
  /* Tight at the top so the first beat is reached almost immediately when
     the reader starts scrolling (owner request, 2026-09-05). */
  padding: var(--sp-4) var(--sp-5) var(--sp-7);
  display: flex;
  flex-direction: column;
  gap: var(--sp-7);
}

.beat {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: center;
}

@media (max-width: 820px) { .beat { grid-template-columns: 1fr; } }

.beat-copy h3 { margin: 0 0 var(--sp-3); font-size: var(--fs-5); line-height: 1.2; }
.beat-copy p { margin: 0; line-height: 1.65; color: var(--text-secondary); }
.beat-copy b { color: var(--text-primary); }

.beat-visual h4 { margin: 0 0 var(--sp-3); font-size: var(--fs-2); color: var(--text-faint); font-weight: 600; }
/* ---------- Explore grid (tab cards) -------------------------- */
.home-explore { max-width: 920px; margin-inline: auto; padding: 0 var(--sp-5) var(--sp-7); }

.explore-head { display: flex; align-items: center; gap: var(--sp-5); margin-bottom: var(--sp-5); }
@media (max-width: 640px) { .explore-head { flex-direction: column; align-items: flex-start; } }

.explore-head h3 { margin: 0 0 var(--sp-1, 6px); font-size: var(--fs-5); }
.explore-head p { margin: 0; color: var(--text-secondary); max-width: 48ch; line-height: 1.6; }

.tab-card-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); }
@media (max-width: 820px) { .tab-card-grid { grid-template-columns: 1fr; } }

/* Tab cards are links — keep the card look, drop link affordances */
.tab-card { position: relative; display: block; text-decoration: none; color: inherit; transition: transform var(--dur-micro) var(--ease-toggle), box-shadow var(--dur-micro) var(--ease-toggle); }
.tab-card:hover { transform: translateY(-3px); }

/* ---------- Reduced motion (§8 courtesy) ---------------------- */
@media (prefers-reduced-motion: reduce) {
  .hero-float--a, .hero-float--b, .hero-float--c { animation: none !important; }
}

/* ============================================================
   Tab 5 · Glossary + inline term hover cards
   ------------------------------------------------------------
   One shared card (#gloss-tip) is positioned by js/tabs/glossary.js.
   Marked-up terms are real links, so click navigates to the full
   entry and keyboard focus shows the same card as hover.
   ============================================================ */

/* ---------- an inline term anywhere on the site --------------- */
.gloss {
  color: inherit;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--accent-2);
  cursor: help;
  transition: color var(--dur-micro) var(--ease-toggle),
    text-decoration-color var(--dur-micro) var(--ease-toggle);
}

.gloss:hover,
.gloss:focus-visible {
  color: var(--accent-solid);
  text-decoration-color: var(--accent-solid);
}

/* ---------- the shared hover card ----------------------------- */
.gloss-tip {
  position: fixed;
  z-index: 60;
  max-width: 320px;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-1);
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow-panel), var(--glass-highlight);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--dur-micro) var(--ease-toggle),
    transform var(--dur-micro) var(--ease-toggle),
    visibility var(--dur-micro);
  pointer-events: none; /* the card must never eat the hover it describes */
}

.gloss-tip.is-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* ---------- the glossary page --------------------------------- */
.glossary-list {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-5);
}

.gloss-entry {
  padding: var(--sp-5);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-panel);
  box-shadow: var(--glass-highlight);
  scroll-margin-top: 96px; /* clear the fixed nav when deep-linked */
  transition: border-color var(--dur-base) var(--ease-toggle),
    box-shadow var(--dur-base) var(--ease-toggle);
}

.gloss-entry h3 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-4);
}

.gloss-entry p {
  margin: 0;
  color: var(--text-secondary);
  /* Full card width. There is no reason to leave half the card empty
     (owner request, 2026-09-05). */
}

.gloss-entry .gloss-more {
  margin-top: var(--sp-3);
  font-size: var(--fs-1);
  color: var(--text-faint);
}

.gloss-entry .gloss-more a {
  color: var(--accent-solid);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

.gloss-entry .gloss-more a:hover,
.gloss-entry .gloss-more a:focus-visible {
  text-decoration-thickness: 2px;
}

/* The entry a reader was sent to by clicking a term. */
.gloss-entry.is-target {
  border-color: var(--accent-solid);
  box-shadow: var(--glass-highlight), 0 0 0 3px color-mix(in srgb, var(--accent-solid) 22%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .gloss-tip { transition-duration: 1ms; transform: none; }
  .gloss-entry { transition: none; }
}

/* ---------- Home beat lists (Tab 1) --------------------------
   Used by the cloud and local beats: short factual lines rather
   than prose, so a reader can scan the shape of each option. */
.flow-list { margin: 0 0 var(--sp-3); padding-left: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2); }
.flow-list li { font-size: var(--fs-2); color: var(--text-secondary); line-height: 1.55; }

/* ============================================================
   Glossary language switch + bilingual entries
   ------------------------------------------------------------
   The switch lives on the glossary page rather than in the site
   header, because it changes the glossary and nothing else. Its
   label names the language it would switch TO.
   ============================================================ */

.gloss-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
}

.gloss-head > div { flex: 1 1 360px; }

.lang-switch {
  flex: none;
  min-height: 40px;
  padding: 0 var(--sp-4);
  border-radius: var(--radius-control);
  border: 1px solid var(--glass-border);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-2);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease-toggle),
    transform var(--dur-micro) var(--ease-toggle);
}

.lang-switch:hover { background: var(--chip-bg); }
.lang-switch:active { transform: scale(0.96); }
.lang-switch[aria-pressed="true"] { border-color: var(--accent-solid); color: var(--accent-solid); }

/* Section heading inside the glossary list. */
.gloss-group {
  margin: var(--sp-6) 0 0;
  font-size: var(--fs-2);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.gloss-group:first-child { margin-top: 0; }

/* The Chinese term, under the English one. Never a replacement for it. */
.gloss-entry .gloss-zh {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-3);
  font-weight: 600;
  color: var(--accent-solid);
}

/* Chinese prose sets better with a little more line height. */
.gloss-entry p[lang="zh-Hans"] { line-height: 1.85; }

/* The hover card carries "Term · 中文" on its own line in Chinese mode,
   so the newline in the text has to survive. */
.gloss-tip { white-space: pre-line; }

/* ============================================================
   Setup tab (M3): OS switch, numbered steps, checkpoints,
   screenshots with HTML callouts, copyable code
   ============================================================ */

/* ---------- Windows / Mac ----------------------------------------
   js/tabs/setup.js stamps <html data-os="win|mac">. Until it does
   (or with no JS), both versions show, joined by an "or". */
:root[data-os="win"] [data-os-only="mac"],
:root[data-os="mac"] [data-os-only="win"],
:root[data-os] .os-or { display: none; }

.os-switch {
  margin: 0;
  padding: 0;
  border: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

.os-switch legend {
  float: left;               /* sits in the flex row instead of on the border */
  margin-right: var(--sp-3);
  font-weight: 600;
  color: var(--text-secondary);
}

/* ---------- Steps ----------------------------------------------- */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* minmax(0, …): a bare column cannot shrink below its widest content,
     and the longest line of a code block would stretch every card past
     a phone's edge. The code scrolls inside its own box instead. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
}

.step { scroll-margin-top: 110px; min-width: 0; }   /* clear the sticky header */
.step > * + * { margin-top: var(--sp-3); }

.step h3 {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-5);
}

.step-num {
  flex: none;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  font-size: var(--fs-3);
  font-weight: 700;
  color: var(--on-accent);
  background: var(--accent-gradient);
}

.step .do,
.step .needs,
.callout-key {
  margin-bottom: 0;
  padding-left: 1.6em;
  display: grid;
  gap: var(--sp-2);
  color: var(--text-secondary);
  line-height: 1.6;
}

.step .do li::marker,
.callout-key li::marker { font-weight: 700; color: var(--accent-solid); }

.step b { color: var(--text-primary); }

/* ---------- Checkpoints ------------------------------------------- */
.checkpoint {
  padding: var(--sp-4);
  border-radius: var(--radius-control);
  border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent);
  background: color-mix(in srgb, var(--ok) 8%, transparent);
}

.checkpoint .shot { margin-bottom: 0; }

.checkpoint-text { color: var(--text-primary) !important; font-weight: 500; }
.tick { color: var(--ok); font-weight: 800; margin-right: 0.3em; }

/* ---------- Notes ------------------------------------------------- */
.note {
  padding: var(--sp-4);
  border-left: 3px solid var(--accent-solid);
  border-radius: 0 var(--radius-control) var(--radius-control) 0;
  background: var(--chip-bg);
}

.note h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-2); }

/* ---------- Screenshots ------------------------------------------
   A .shot holds one <img> at its final path. If the file is missing,
   js/tabs/setup.js adds .is-missing and the frame shows the image's
   alt text and file name instead, at the planned 16:10 shape. */
.shot {
  position: relative;
  margin: var(--sp-3) 0;
  border-radius: var(--radius-control);
  border: 1px solid var(--glass-border);
  overflow: hidden;
  background: var(--chip-bg);
}

.shot img { display: block; width: 100%; height: auto; }
.shot--small { max-width: 520px; }

/* Images load lazily, so a frame further down does not know yet whether
   its file exists. Hold the planned 16:10 space until it does, so the
   page never jumps as the student scrolls. A loaded image takes its
   own shape. */
.shot:not(.is-loaded) { aspect-ratio: 16 / 10; }

.shot.is-missing {
  border-style: dashed;
  border-width: 2px;
}

.shot.is-missing img { display: none; }

.shot.is-missing::after {
  content: "Screenshot coming: " attr(data-alt) "\A" attr(data-file);
  white-space: pre-wrap;
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  text-align: center;
  font-size: var(--fs-1);
  line-height: 1.6;
  color: var(--text-faint);
}

/* The window shot draws a rough map of the five parts while the real
   screenshot is missing, so the callouts point at something. */
.shot-schematic { display: none; }

.shot--window.is-missing::after { content: none; }

.shot--window.is-missing .shot-schematic {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 4% 20% 1fr;
  grid-template-rows: 1fr 30% 3%;
  gap: 2px;
  padding: 2px;
}

.shot-schematic span { border-radius: 4px; background: var(--track); }
.sch-activity { grid-column: 1; grid-row: 1 / 3; }
.sch-side     { grid-column: 2; grid-row: 1 / 3; }
.sch-editor   { grid-column: 3; grid-row: 1; opacity: 0.55; }
.sch-panel    { grid-column: 3; grid-row: 2; }
.sch-status   { grid-column: 1 / -1; grid-row: 3; background: var(--accent-solid) !important; opacity: 0.6; }

.callout {
  position: absolute;
  left: var(--x);
  top: var(--y);
  transform: translate(-50%, -50%);
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 50%;
  font-size: var(--fs-1);
  font-weight: 800;
  color: var(--on-accent);
  background: var(--accent-gradient);
  box-shadow: 0 0 0 3px var(--bg-base), var(--shadow-panel);   /* ring lifts it off any screenshot */
  z-index: 1;
}

/* ---------- Copyable code ----------------------------------------- */
.code-block { position: relative; }

.code-block pre {
  margin: 0;
  padding: var(--sp-4);
  padding-right: 88px;          /* room for the Copy button */
  overflow-x: auto;
  border-radius: var(--radius-control);
  border: 1px solid var(--glass-border);
  background: var(--chip-bg);
  font-size: var(--fs-1);
  line-height: 1.6;
}

/* Inside a block, code is the block: no per-word chip. */
.code-block pre code { padding: 0; border: 0; background: none; font-size: inherit; overflow-wrap: normal; }

.copy-btn {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  min-height: 32px;
  padding: 0 var(--sp-3);
  border-radius: 8px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  color: var(--text-primary);
  font: 600 var(--fs-1) var(--font-sans);
  cursor: pointer;
}

.copy-btn:hover { background: var(--chip-bg); }
.copy-btn.is-done { color: var(--ok); border-color: var(--ok); }
