/*
 * design/components.css — shared component styles built on design/tokens.css.
 * Every NEW native lesson module uses these instead of hand-styling its own
 * cards / activity tags / buttons / instruction banners. Variants change
 * accent only — radius, padding, border, typography and base surface are
 * shared. Loaded by lessons/mount-lesson.js for every native module.
 */

/* ============================================================================
   LESSON SHELL — the fixed chrome every native module mounts into
   (lessons/mount-lesson.js renders these exact classes). One shell, reused by
   every module, styled identically to the approved concave lesson's chrome.
   ============================================================================ */
.ds-lesson-root {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: radial-gradient(120% 90% at 78% 30%, #174a3a 0%, var(--stage-bg) 45%, var(--app-bg) 100%);
  color: var(--text-primary);
  font-family: var(--font-family);
  -webkit-user-select: none;
  user-select: none;
}
.ds-lesson-root.is-ended .ds-lesson-stage { opacity: .22; transition: opacity .5s ease; }
.ds-lesson-root.is-ended .ds-teleprompter,
.ds-lesson-root.is-ended .ds-progress,
.ds-lesson-root.is-ended .ds-subhint,
.ds-lesson-root.is-ended .ds-instruction-banner,
.ds-lesson-root.is-ended .ds-controls,
.ds-lesson-root.is-ended .ds-skip-btn,
.ds-lesson-root.is-ended .ds-mute-btn { opacity: 0; pointer-events: none; }
.ds-lesson-root.is-ended .ds-advance { display: none; }

.ds-lesson-stage { position: absolute; inset: 0; }
.ds-lesson-stage .ds-world,
.ds-lesson-stage > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
/* MOBILE IS NOT SHRUNK DESKTOP. .ds-lesson-root.is-compact-vp (set by
   mount-lesson.js from a real matchMedia, not guessed) is the signal a
   stage may consult to pick its OWN mobile-appropriate viewBox/composition
   — reframing the same scientific relationships, never just fitting the
   desktop composition into less width. No stage does this yet; this rule
   and the class it reads exist so a later, scene-specific pass can. */

.ds-teleprompter {
  position: absolute;
  left: 50%;
  top: clamp(30px, 8vh, 78px);
  transform: translateX(-50%);
  width: min(34rem, calc(100vw - 36px));
  margin: 0;
  text-align: center;
  font-weight: var(--font-weight-title);
  letter-spacing: -0.018em;
  line-height: 1.14;
  font-size: var(--font-size-title);
  color: var(--text-primary);
  text-shadow: 0 2px 22px rgba(4, 20, 14, .55), 0 1px 3px rgba(4, 20, 14, .5);
  pointer-events: none;
}
.ds-subhint {
  position: absolute;
  left: 50%;
  top: calc(clamp(30px, 8vh, 78px) + 3.1em);
  transform: translateX(-50%);
  margin: 0;
  width: min(30rem, calc(100vw - 48px));
  text-align: center;
  font-weight: var(--font-weight-body);
  line-height: 1.35;
  font-size: var(--font-size-explanation);
  color: var(--text-secondary);
  text-shadow: 0 1px 12px rgba(4, 20, 14, .5);
  pointer-events: none;
  min-height: 1.4em;
}

.ds-advance { position: absolute; inset: 96px 0 96px 0; background: none; border: 0; cursor: pointer; pointer-events: none; }
.ds-lesson-root[data-state="ready"] .ds-advance { pointer-events: auto; }

.ds-controls {
  position: absolute;
  left: 50%;
  bottom: calc(12px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 8;
  width: min(38rem, calc(100vw - 20px));
  display: flex;
  align-items: center;
  gap: 8px;
}
.ds-ctrl-spacer { flex: 1; }
.ds-controls button {
  appearance: none;
  border: 1px solid rgba(191, 224, 207, .22);
  background: rgba(9, 32, 24, .5);
  color: var(--text-secondary);
  font: var(--font-weight-body) .92rem var(--font-family);
  padding: 11px 15px;
  min-height: var(--control-height);
  border-radius: var(--radius-button);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
.ds-controls button:hover:not(:disabled) { background: rgba(9, 32, 24, .8); color: var(--text-primary); }
.ds-controls button:disabled { opacity: .28; cursor: default; }
.ds-ctrl-next { border-color: transparent; background: rgba(89, 230, 208, .16); color: var(--text-muted); font-weight: 800; padding: 12px 22px; }
.ds-ctrl-next.is-ready { background: linear-gradient(180deg, #6fe9d7, #22b9a6); color: #05231d; }
.ds-ctrl-next:disabled { opacity: 1; }
.ds-ctrl-mid { min-width: 46px; justify-content: center; }
.ds-ctrl-mid[data-mode="pause"], .ds-ctrl-mid[data-mode="resume"] {
  border-color: rgba(89, 230, 208, .5); background: rgba(89, 230, 208, .14); color: var(--text-primary);
}

.ds-mute-btn, .ds-skip-btn { position: absolute; z-index: 6; }
.ds-mute-btn {
  top: 10px; right: max(10px, env(safe-area-inset-right));
  width: 38px; height: 38px; border-radius: var(--radius-button);
  border: 1px solid rgba(191, 224, 207, .22); background: rgba(9, 32, 24, .55);
  color: var(--text-secondary); font-size: 1rem; cursor: pointer; display: grid; place-items: center;
}
.ds-skip-btn {
  top: 56px; right: max(10px, env(safe-area-inset-right));
  border: 1px solid rgba(191, 224, 207, .18); border-radius: var(--radius-pill);
  background: rgba(9, 32, 24, .4); color: var(--text-muted);
  font: 700 .78rem var(--font-family); letter-spacing: .04em; padding: 6px 12px; min-height: 32px; cursor: pointer;
}

/* Touch-target expansion: the visible chrome above stays exactly the size
   it was reviewed at — these grow only the invisible hit area (a
   transparent ::after, so nothing paints) toward ~44px, the accepted
   minimum. A 1-2px overlap between two adjacent expanded targets is an
   accepted trade-off; it never changes which control a tap's majority
   area lands in. */
.ds-mute-btn::after { content: ''; position: absolute; inset: -3px; }
.ds-skip-btn::after { content: ''; position: absolute; top: -6px; bottom: -6px; left: -2px; right: -2px; }

.ds-progress { position: absolute; top: 12px; left: 12px; width: min(46vw, 220px); height: 24px; padding: 0; background: none; border: 0; cursor: pointer; z-index: 6; }
.ds-progress::after { content: ''; position: absolute; top: -10px; bottom: -10px; left: 0; right: 0; }
.ds-pbar { display: block; height: 5px; border-radius: var(--radius-pill); background: rgba(255, 255, 255, .16); overflow: hidden; }
.ds-pfill { display: block; height: 100%; width: 0; background: var(--accent-primary); transition: width .4s ease; }

.ds-trail {
  position: absolute; left: 12px; top: 44px; z-index: 12;
  width: min(24rem, calc(100vw - 28px)); max-height: 70vh; overflow-y: auto;
  background: var(--surface); color: var(--text-on-surface);
  border-radius: var(--radius-card); padding: 14px 16px 12px; box-shadow: var(--shadow-modal);
}
.ds-trail-head { display: flex; align-items: center; justify-content: space-between; }
.ds-trail-head h2 { margin: 0; font-size: 1.05rem; }
.ds-trail-close { border: 0; background: transparent; color: var(--text-on-surface-muted); font-size: 1rem; cursor: pointer; width: 30px; height: 30px; border-radius: 8px; }
.ds-trail-list { list-style: none; margin: 10px 0 4px; padding: 0; }
.ds-trail-item { width: 100%; text-align: left; border: 1px solid var(--surface-border); background: #f6fbf7; color: var(--text-on-surface); border-radius: 10px; padding: 10px 12px; font: 600 .95rem var(--font-family); cursor: pointer; margin: 4px 0; }
.ds-trail-item.is-current { background: #eaf6f0; border-color: #9fd9c4; cursor: default; }
.ds-trail-empty { color: var(--text-on-surface-muted); font-size: .9rem; padding: 8px 4px; }

.ds-endcard {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(30rem, calc(100vw - 40px));
  background: var(--surface); color: var(--text-on-surface);
  border-radius: 22px; padding: 30px 26px 26px; text-align: center;
  box-shadow: var(--shadow-modal); z-index: 10;
}
.ds-endcard h2 { margin: 0 0 6px; font-size: 2rem; letter-spacing: -0.02em; }
.ds-endcard p { margin: 0 auto 20px; max-width: 24rem; font-size: 1.02rem; line-height: 1.5; color: #3a5a4c; }
.ds-endcard-btns { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

@media (min-width: 1000px) { .ds-teleprompter { top: clamp(28px, 9vh, 96px); } }
@media (max-width: 430px) {
  .ds-controls { width: calc(100vw - 16px); gap: 6px; }
  .ds-ctrl-prev, .ds-ctrl-next { font-size: .9rem; }
  /* narrow phones: the activity tag (top-left, up to 2 lines) and the
     teleprompter (centred headline) share the top of the screen — give the
     headline a fixed, generous clearance instead of the vh-based clamp so
     the two never collide, regardless of how long the activity name is. */
  .ds-teleprompter { top: 92px; }
  .ds-subhint { top: calc(92px + 3.1em); }
}
@media (max-height: 480px) and (orientation: landscape) {
  .ds-teleprompter { top: 8px; font-size: clamp(1.1rem, 5vh, 1.7rem); }
  .ds-subhint { top: 52px; }
  .ds-controls { bottom: 8px; }
  /* Short landscape (e.g. 844x390): the bottom-anchored instruction/result
     stack has far less room to work with. Compact ITS OWN chrome (padding,
     the fixed clearance above controls, text size) and cap its height with
     internal scroll as a hard backstop — this is the shared stack's own
     footprint shrinking, not a per-scene diagram change, so it can never
     grow up into the headline the way Astra found. */
  .ds-instruction-banner {
    bottom: calc(var(--control-height) + 34px + var(--ds-bottom-stack, 0px));
    padding: 8px 14px;
    max-height: 34vh;
    overflow-y: auto;
  }
  .ds-instruction-banner .ds-instr-text { font-size: 1rem; }
  .ds-bottom-card { max-height: 34vh; overflow-y: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .ds-lesson-root * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ---------------------------------------------------------------- card ---- */
/* Base = the approved concave lesson's "result card" (explore-card in
   lesson.css): a light paper surface floating on the dark stage. */
.ds-card {
  background: var(--surface);
  color: var(--text-on-surface);
  border: var(--card-border);
  border-radius: var(--radius-card);
  padding: var(--card-padding);
  box-shadow: var(--shadow-card);
}
.ds-card-eyebrow {
  margin: 0 0 8px;
  font-size: var(--font-size-small);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-on-surface-muted);
}
.ds-card-title { margin: 0 0 4px; font-size: 1rem; font-weight: 800; color: var(--text-on-surface); }
.ds-card-body  { margin: 0; font-size: .92rem; font-weight: 600; line-height: 1.45; color: var(--text-on-surface); }
.ds-card-body + .ds-card-body { margin-top: 6px; }

/* result grid — label ABOVE a larger bold value (matches .explore-readout) */
.ds-result-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 18px; }
.ds-result-row { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ds-result-row dt { font-size: .6rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--text-on-surface-muted); margin: 0; }
.ds-result-row dd { margin: 0; font-size: 1.02rem; font-weight: 800; line-height: 1.15; color: var(--text-on-surface); }
.ds-result-row .is-emph { color: var(--surface-emph-real); }
.ds-card.is-virtual { border-color: var(--surface-border-virtual); }
.ds-card.is-virtual .is-emph { color: var(--surface-emph-virtual); }

/* variants — accent only, same base */
.ds-card--instruction { border-left: 4px solid var(--accent-primary); }
.ds-card--memory { border-left: 4px solid var(--accent-secondary); }
.ds-card--application { text-align: left; }
.ds-card--observation .ds-card-eyebrow { color: var(--surface-emph-real); }

/* bullet list inside a card, consistent spacing */
.ds-card ul.ds-list { margin: 6px 0 0; padding-left: 1.1em; }
.ds-card ul.ds-list li { margin: 3px 0; font-size: .9rem; font-weight: 600; }

/* --------------------------------------------------------- activity tag ---- */
/* Plain text, no chip/box — matches the approved intro lesson exactly. */
.ds-activity-tag {
  position: absolute;
  top: 44px;
  left: max(12px, env(safe-area-inset-left));
  margin: 0;
  z-index: 6;
  max-width: min(62vw, 320px);
  display: flex;
  flex-direction: column;
  gap: 2px;
  pointer-events: none;
  opacity: .92;
}
.ds-activity-tag .ds-at-num {
  font: 800 10px var(--font-family);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--focus-color);
}
.ds-activity-tag .ds-at-name {
  font: 700 12px var(--font-family);
  color: var(--text-secondary);
  line-height: 1.2;
}
@media (max-height: 460px) { .ds-activity-tag { top: 30px; } }

/* ------------------------------------------------------------- buttons ---- */
.ds-btn {
  appearance: none;
  border: 1.5px solid transparent;
  border-radius: var(--radius-button);
  padding: 12px 20px;
  min-height: var(--control-height);
  font: 700 1rem var(--font-family);
  cursor: pointer;
  transition: transform .08s ease, background .15s ease;
}
.ds-btn:active { transform: translateY(1px); }
.ds-btn-primary { background: var(--paper-ink); color: var(--paper); }
.ds-btn-primary:hover { background: #1f4c3b; }
.ds-btn-ghost { background: transparent; border-color: #b9d3c6; color: var(--paper-ink); }
.ds-btn-ghost:hover { background: #e2efe6; }

/* ------------------------------------------------------- drag / gesture cue */
/* Matches the concave lesson's bobbing `.cue` pill exactly. */
.ds-drag-cue {
  position: absolute;
  left: 50%;
  transform: translate(-50%, 0);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: var(--radius-pill);
  background: rgba(9, 32, 24, .82);
  border: 1px solid rgba(89, 230, 208, .5);
  color: var(--text-primary);
  font-weight: 700;
  font-size: .95rem;
  pointer-events: none;
  z-index: 9; /* above the instruction banner (7) and any bottom card — a
                 drag cue that can be silently hidden behind a card defeats
                 its purpose */
  animation: ds-cue-bob 1.6s ease-in-out infinite;
  white-space: nowrap;
}
.ds-drag-cue .ds-cue-arrow { color: var(--accent-primary); font-size: 1.1rem; }
.ds-drag-cue .ds-cue-word { letter-spacing: .04em; text-transform: uppercase; font-size: .8rem; }
@keyframes ds-cue-bob {
  0%, 100% { transform: translate(calc(-50% - 12px), 0); }
  50%      { transform: translate(calc(-50% + 12px), 0); }
}

/* ------------------------------------------------ persistent instruction ---- */
/* Sound-independent "what do I do?" banner for every interactive beat.
   Always readable text; narration is supplementary, never the only channel. */
.ds-instruction-banner {
  position: absolute;
  left: 50%;
  /* --ds-bottom-stack: set by the stage (in px) when a result/memory card is
     ALSO anchored to the bottom, so the two never overlap. One layout
     contract, not a per-scene pixel hack. */
  bottom: calc(var(--control-height) + 56px + var(--ds-bottom-stack, 0px));
  transform: translateX(-50%);
  width: min(30rem, calc(100vw - 28px));
  background: var(--surface);
  color: var(--text-on-surface);
  border: var(--card-border);
  border-radius: var(--radius-card);
  padding: 12px 18px;
  box-shadow: var(--shadow-card);
  text-align: center;
  z-index: 7;
}
.ds-instruction-banner .ds-instr-eyebrow {
  margin: 0 0 4px;
  font-size: var(--font-size-small);
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-on-surface-muted);
}
.ds-instruction-banner .ds-instr-text {
  margin: 0;
  font-size: var(--font-size-instruction);
  font-weight: 700;
  line-height: 1.35;
}
.ds-instruction-banner[data-state="acknowledge"] { border-color: var(--accent-primary); }
.ds-instruction-banner[data-state="acknowledge"] .ds-instr-eyebrow { color: var(--surface-emph-real); }
.ds-instruction-banner[data-state="success"] { border-color: var(--accent-secondary); }
.ds-instruction-banner[data-state="success"] .ds-instr-eyebrow { color: var(--surface-emph-virtual); }

/* ------------------------------------------------- illustration placeholder */
/* For a FIXED real-world visual we don't yet have a final asset for. Marks
   itself clearly as temporary and states exactly what to generate — never a
   low-quality pseudo-realistic SVG presented as final art. */
.ds-illustration-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: rgba(255, 255, 255, .04);
  border: 1.5px dashed var(--text-muted);
  border-radius: var(--radius-card);
  color: var(--text-secondary);
  text-align: center;
  padding: var(--space-md);
  min-height: 96px;
}
.ds-illustration-placeholder .ds-ph-icon { font-size: 2rem; opacity: .85; line-height: 1; }
.ds-illustration-placeholder .ds-ph-label { font-size: .78rem; font-weight: 700; color: var(--text-secondary); }
.ds-illustration-placeholder .ds-ph-note { font-size: .64rem; color: var(--text-muted); font-style: italic; max-width: 34ch; }

/* --------------------------------------------------------- layout helpers */
.ds-scene-html { position: absolute; inset: 0; pointer-events: none; }
.ds-scene-html > * { pointer-events: auto; }
.ds-grid-2x2 {
  position: absolute;
  inset: clamp(120px, 22vh, 200px) clamp(16px, 5vw, 60px) calc(var(--control-height) + 26px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  gap: var(--space-md);
  overflow-y: auto;
}
.ds-grid-2x2 > * { min-height: 0; overflow-y: auto; }
.ds-split-row {
  position: absolute;
  inset: clamp(110px, 20vh, 200px) clamp(16px, 5vw, 48px) calc(var(--control-height) + 26px);
  display: flex;
  gap: var(--space-lg);
  align-items: stretch;
}
.ds-split-row > * { flex: 1 1 0; min-width: 0; min-height: 0; overflow-y: auto; }
.ds-columns-2 {
  position: absolute;
  inset: clamp(110px, 20vh, 200px) clamp(16px, 5vw, 60px) calc(var(--control-height) + 26px);
  display: flex;
  gap: var(--space-lg);
}
.ds-columns-2 > * { flex: 1 1 0; min-width: 0; min-height: 0; overflow-y: auto; }
.ds-bottom-card {
  position: absolute;
  left: 50%;
  bottom: calc(var(--control-height) + 26px);
  transform: translateX(-50%);
  width: min(34rem, calc(100vw - 28px));
}

@media (max-width: 700px) {
  .ds-grid-2x2 { grid-template-columns: 1fr; overflow-y: auto; row-gap: var(--space-sm); }
  .ds-split-row { flex-direction: column; overflow-y: auto; }
  .ds-columns-2 { flex-direction: column; overflow-y: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .ds-drag-cue { animation: none; }
}
