/* ── Story page layout ────────────────────────────────────────────────────────
   Native body scroll. Two columns below the site header: the left text column
   flows with the page; the right strip panel is sticky within the column.    */

/* ── Column container ────────────────────────────────────────────────────── */
#columns {
  display: grid;
  grid-template-columns: var(--left-w) minmax(0, 1fr);
  align-items: start;
  margin-top: var(--header-h);
}

/* ── Left column (story text, flows with body scroll) ────────────────────── */
#left {
  padding: 52px 40px 96px;
  position: relative;
  z-index: 2; /* landing title overlays the full-bleed hero visual */
}

/* ── Right column (strip panel, sticky) ──────────────────────────────────── */
#right {
  position: sticky;
  top: var(--header-h);
  height: calc(100vh - var(--header-h));
  width: 100%;
  overflow: hidden;
  border-left: 1px solid var(--sep);
  transition: width 0.6s cubic-bezier(0.25,0.1,0.25,1),
              margin-left 0.6s cubic-bezier(0.25,0.1,0.25,1),
              border-color 0.4s ease;
}

/* ── Landing hero — visual bleeds across both columns, title overlaid.
   Driven by scroll position (story-base.js), not section activation: the
   bleed releases as soon as the reader commits to scrolling, well before the
   first content section needs the left column clear. ─────────────────────── */
body.hero-bleed #right {
  width: calc(100% + var(--left-w));
  margin-left: calc(-1 * var(--left-w));
  border-left-color: transparent;
}

/* ── Section structure ────────────────────────────────────────────────────── */
.text-section {
  margin-bottom: 62vh;
}
.text-section.before-sub { margin-bottom: 28px; }

.chapter-tag {
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 6px;
}

h2.sec-heading {
  font-family: var(--font-serif);
  font-size: 22px; font-weight: 600; line-height: 1.3;
  color: var(--text); margin-bottom: 14px;
}

.sub-section h3.sec-heading {
  font-family: var(--font-serif);
  font-size: 17px; font-weight: 500; line-height: 1.4;
  color: var(--text); margin-bottom: 12px;
}

.sec-body {
  font-size: 14px; color: var(--text-dim); line-height: 1.85;
}
.sec-body p { margin: 0; }
.sec-body p + p { margin-top: 12px; }

/* ── Expandables ─────────────────────────────────────────────────────────── */
.expandables { margin-top: 20px; }
.expandable-wrap + .expandable-wrap { margin-top: 4px; }

.expand-btn {
  background: none; border: none; cursor: pointer; padding: 4px 0;
  font-family: var(--font-sans); font-size: 12.5px;
  color: var(--text-dim);
  display: flex; align-items: center; gap: 5px;
  transition: color 0.15s;
}
.expand-btn .arrow {
  font-style: normal; display: inline-block;
  transition: transform 0.2s; line-height: 1;
}
.expand-btn.open .arrow { transform: rotate(90deg); }
.expand-btn:hover { color: var(--text); }

.expand-body {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.35s ease;
  padding-left: 12px;
  border-left: 2px solid var(--sep);
  margin-top: 0;
}
.expand-body.open { max-height: 800px; margin-top: 8px; }
.expand-body .sec-body { padding: 8px 0 10px; }

/* ── Root selector in header ─────────────────────────────────────────────── */
.root-btns {
  display: flex; gap: 3px; flex-wrap: wrap;
}
.root-btn {
  padding: 3px 8px;
  background: none; border: 1px solid var(--sep); border-radius: 4px;
  font-family: var(--font-sans); font-size: 11px;
  color: var(--text-dim); cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
  line-height: 1.6;
}
.root-btn:hover { color: var(--text); border-color: #ccc8c0; }
.root-btn.active {
  background: hsl(var(--nh), 52%, 90%);
  color:      hsl(var(--nh), 52%, 28%);
  border-color: hsl(var(--nh), 52%, 72%);
  font-weight: 600;
}
[data-theme="dark"] .root-btn.active {
  background: hsl(var(--nh), 50%, 18%);
  color:      hsl(var(--nh), 50%, 74%);
  border-color: hsl(var(--nh), 50%, 40%);
}

/* ── Story landing section ───────────────────────────────────────────────── */
.story-landing {
  min-height: calc(100vh - var(--header-h) - 52px); /* 52px = #left top padding */
  padding: 20px 0 80px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
/* Text shield over the full-bleed hero visual: the full landing column is
   near-solid paper (strings almost invisible behind the copy), feathering out
   to the fully visible hero across an eased ~120px band on the right.
   Kept deliberately in S5 — Foundation's hero is the full-bleed string family
   (§2a), and the copy needs this shield to stay legible over it. */
.story-landing::before {
  content: '';
  position: absolute;
  inset: -52px -100px -20px -40px;   /* full landing height, incl. every paragraph */
  background: linear-gradient(to right,
    color-mix(in srgb, var(--bg) 97%, transparent) 0,
    color-mix(in srgb, var(--bg) 97%, transparent) calc(100% - 130px),
    color-mix(in srgb, var(--bg) 76%, transparent) calc(100% - 88px),
    color-mix(in srgb, var(--bg) 38%, transparent) calc(100% - 40px),
    transparent 100%);
  pointer-events: none;
  z-index: -1;
}
.story-landing-tag {
  display: block; font-size: 10px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 14px;
}
.story-landing-title {
  font-family: var(--font-serif);
  font-size: 30px; font-weight: 600; line-height: 1.2;
  color: var(--text); margin-bottom: 18px;
}
.story-landing-desc {
  font-size: 14px; color: var(--text-dim); line-height: 1.85;
  max-width: 320px;
}

/* ── Scroll hint ─────────────────────────────────────────────────────────── */
.scroll-hint {
  position: fixed;
  bottom: 40px;
  left: 28px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  transition: opacity 0.5s ease;
  z-index: 10;
  pointer-events: none;
}
.scroll-hint.gone { opacity: 0; }
.scroll-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-dim);
}
.scroll-arrow {
  font-size: 20px;
  color: var(--text-dim);
  animation: scrollBounce 1.6s ease-in-out infinite;
  line-height: 1;
}
@keyframes scrollBounce {
  0%, 100% { opacity: 0.7; transform: translateY(0); }
  50%       { opacity: 0.2; transform: translateY(5px); }
}

/* ── Wave background (right panel) ───────────────────────────────────────── */
.wave-bg {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  justify-content: center; gap: 0;
  padding: 20px 24px;
  pointer-events: none;
  transition: opacity 0.4s ease, bottom 0.6s cubic-bezier(0.25,0.1,0.25,1),
              top 0.6s cubic-bezier(0.25,0.1,0.25,1);
  z-index: 0;
}
.wave-bg.compressed {
  bottom: calc(100% - var(--story-wave-h, 45%)); /* default 55% from bottom = top 45% */
  padding: 8px 24px;
}
.wave-row {
  flex: 1; min-height: 0;
  position: relative;
  transition: opacity 0.35s ease;
}
.wave-row svg {
  width: 100%; height: 130%;  /* slightly taller than row → overlap */
  display: block; overflow: visible;
}
.wave-label {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 11px;
  font-weight: 500;
  font-family: var(--font-sans);
  color: hsl(var(--wave-hue, 30) 38% 28%);
  letter-spacing: 0.01em;
  pointer-events: none;
  white-space: nowrap;
  z-index: 1;
  /* Frosted pill */
  background: rgba(250, 248, 244, 0.84);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  padding: 2px 9px 3px;
  border-radius: 5px;
  border: 1px solid hsl(var(--wave-hue, 30) 38% 72%);
  line-height: 1.4;
}

/* Strip items sit above the wave bg */
.strip-item { z-index: 1; }

/* ── Guitar neck panel ───────────────────────────────────────────────────── */
.story-neck {
  position: absolute;
  /* Taller + full-width so the 3D neck has room to tilt/roll without clipping at
     the canvas edges; bottom still aligns with the viz zone. The extra area is
     transparent headroom around the centred neck. */
  top: calc(var(--story-viz-h, 40%) - 220px); /* bottom of neck aligns with viz zone */
  left: calc((100% - var(--story-neck-w, 100%)) / 2);
  right: calc((100% - var(--story-neck-w, 100%)) / 2);
  height: 220px;
  padding: 0;
  background: transparent;
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
  z-index: 2;
}
.story-neck.visible {
  opacity: 1;
  pointer-events: all;
}
/* S7b zone contract (field pages set config.neckTop): the neck zone is the
   bottom band of the panel — the porcelain slab and its shadow live there
   alone, below the strips zone. --story-neck-top is zone boundary 2. */
#right.zoned .story-neck {
  top: var(--story-neck-top, 74%);
  bottom: 0;
  height: auto;
}
.story-neck svg {
  width: 100%; height: 100%; display: block;
}
/* S11e ③: the SVG fallback gets an opaque --bg backdrop on guides that seat the
   neck low over the strips zone (Diatonic, config.neck.opaqueBg) — travelling
   strips passing up behind it must disappear, never show through. The 3D neck
   stays transparent (it floats with a shadow); only the SVG fallback opts in. */
/* The fallback's opaque backdrop is the .neck-paper rect INSIDE the svg (round
   7b) — content-sized + 15px, never the full container band. */
.story-neck.neck-opaque { background: transparent; }

/* ── Interval strip dimming ──────────────────────────────────────────────── */
/* Non-highlighted pills in interval sub-sections */
.note-pill.int-dim {
  opacity: 0.18;
}

/* ── Waveform display (in section body text) ────────────────────────────── */
.waveform-wrap {
  margin-top: 16px;
}
.waveform-svg {
  width: 100%; height: auto; display: block;
  max-width: 320px;
}
.wf-row-label {
  font-size: 10.5px; font-family: var(--font-sans);
  color: var(--text-faint); margin-bottom: 3px;
  letter-spacing: 0.01em;
}
.waveform-label {
  font-size: 10px; color: var(--text-faint);
  text-align: right; margin-top: 4px;
}

/* ── Piano SVG wrapper ───────────────────────────────────────────────────── */
.piano-wrap {
  margin: 14px 0;
  overflow-x: auto;
}
.piano-svg {
  display: block;
  min-width: 200px;
}

/* ── Int song note ───────────────────────────────────────────────────────── */
.int-song-note {
  font-size: 12.5px; color: var(--text-dim);
  font-style: italic; border-left: 2px solid var(--sep);
  padding-left: 10px; margin-top: 10px;
}

/* ── Interval cards (Notes families, §4) ─────────────────────────────────── */
.int-family-sub {
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-faint);
  margin: -2px 0 10px !important;
}
.int-card {
  margin: 20px 0; padding: 14px 0 2px;
  border-top: 1px solid var(--sep);
}
.int-card-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 8px;
}
.int-card-flower { flex-shrink: 0; display: inline-flex; }
.int-card-flower svg { display: block; }
.int-card-title { flex: 1; font-size: 15px; color: var(--text); line-height: 1.3; }
.int-card-title strong { color: var(--accent); font-weight: 700; }
.int-ratio {
  font-size: 11.5px; color: var(--text-faint); font-family: var(--font-sans);
  white-space: nowrap; margin-left: 2px;
}
.int-play {
  flex-shrink: 0; cursor: pointer;
  font-size: 11px; font-family: var(--font-sans); color: var(--text-dim);
  background: none; border: 1px solid var(--sep); border-radius: 14px;
  padding: 3px 11px; transition: border-color .15s, color .15s, background .15s;
}
.int-play:hover { border-color: var(--accent); color: var(--accent); }
.int-play.playing { background: var(--accent); border-color: var(--accent); color: #fff; }
.int-play-sm { padding: 2px 9px; margin: 0 3px; }
.int-wave-cue {
  font-size: 11.5px; color: var(--text-faint); font-style: italic;
  margin-top: 6px;
}
.int-wave-cue::before { content: "wave: "; font-style: normal; opacity: 0.7; }
.int-ladder-note, .int-confession {
  font-size: 12.5px; color: var(--text-dim); margin-top: 14px;
}
.int-confession {
  border-left: 2px solid var(--accent);
  padding: 10px 14px; background: rgba(196,92,46,0.05);
  border-radius: 0 6px 6px 0;
}
.int-compound-row { margin-top: 12px; font-size: 13px; color: var(--text-dim); }
.int-aside { font-size: 12.5px; color: var(--text-dim); margin-top: 8px; }
/* Inline mini sum-figure (Two Notes, §4): two waves + = their combined sum. */
.int-sum-fig {
  margin: 14px 0; display: block; max-width: 260px;
}
.int-sum-fig svg { width: 100%; height: auto; display: block; }

/* ── Guitar tab notation ─────────────────────────────────────────────────── */
.tab-notation {
  margin: 8px 0 4px;
  overflow-x: auto;
  border-radius: 6px;
}

/* ── Waveform sum explanation ────────────────────────────────────────────── */
.wf-explain {
  font-size: 12px; color: var(--text-faint);
  font-style: italic; margin-top: 8px; line-height: 1.7;
}

/* ── Strip label click target ─────────────────────────────────────────────── */
.strip-label { cursor: pointer; }
.strip-label:hover strong { color: var(--accent); }

/* ── Chord flower ─────────────────────────────────────────────────────────── */
.chord-flower { flex-shrink: 0; margin-left: 8px; }

/* ── Petal highlight on note hover (scale transform — works in Safari) ────── */
.chord-flower ellipse.highlighted {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(1.4);
  opacity: 1 !important;
}

/* ── Inline flower in section heading ─────────────────────────────────────── */
.sec-hdr-flower {
  display: inline-flex;
  vertical-align: middle;
  margin-right: 8px;
}

/* ── Inline flower + arc paragraph (major/minor scale body, L-shaped wrap) ── */
.scale-arc-intro { margin: 14px 0; overflow: hidden; }
.scale-arc-flower { float: left; margin: 2px 14px 8px 0; }

/* ── Right panel placeholder (shown before first section activates) ───────── */
#right:empty::after {
  content: '';
  display: block;
}

/* ── Inline root selector (scales story intro) ───────────────────────────── */
.inline-root-wrap {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 14px;
}

.inline-root-label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-faint);
}

.inline-root-select {
  appearance: none;
  background: var(--bg-panel);
  border: 1px solid var(--sep);
  border-radius: 6px;
  color: var(--text);
  font-size: 13px; font-weight: 500;
  padding: 4px 28px 4px 10px;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23888'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 8px 5px;
}

.inline-root-select:focus {
  outline: none;
  border-color: var(--accent);
}

/* ── Note sequence spans (inline note lists in scale text) ──────────────── */
.note-seq {
  font-weight: 500; letter-spacing: 0.03em; white-space: nowrap;
}

/* ── Inline scale flower ─────────────────────────────────────────────────── */
.scale-flower-wrap {
  display: flex;
  justify-content: center;
  margin: 18px 0 16px;
}

/* h2 headings that contain a flower + text */
h2.sec-heading:has(.sec-hdr-flower) {
  display: flex;
  align-items: center;
}

/* ── Scale steps/notes visual table ──────────────────────────────────────── */
.scale-vis {
  border-collapse: collapse;
  margin: 10px 0 18px;
}

.scale-vis .sv-st {
  text-align: center;
  color: var(--text-faint);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0 0 4px;
  min-width: 28px;
  vertical-align: bottom;
}

.scale-vis .sv-nt {
  text-align: center;
  font-weight: 600;
  font-size: 14px;
  padding: 4px 0 0;
  min-width: 28px;
  vertical-align: top;
}

.scale-vis .sv-sep {
  text-align: center;
  color: var(--sep);
  font-size: 12px;
  width: 16px;
  padding: 0;
}

.scale-vis tr:first-child .sv-sep { vertical-align: bottom; padding-bottom: 4px; }
.scale-vis tr:last-child  .sv-sep { vertical-align: top;    padding-top: 4px; }

/* ── Scales landing visualization (right panel) ─────────────────────────── */
.scales-viz {
  position: absolute;
  top: 0; left: 0;
  pointer-events: none;
  z-index: 0;
  transition: opacity 0.4s ease;
}

/* ── Modes table ─────────────────────────────────────────────────────────── */
.modes-table {
  border-collapse: collapse;
  margin: 14px 0 20px;
  width: 100%;
}
.modes-table thead th {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-faint);
  padding: 0 8px 6px 0; border-bottom: 1px solid var(--sep);
  text-align: left; vertical-align: bottom;
}
.modes-table thead .mt-flower-head { padding-right: 0; }
.modes-table tbody tr:first-child td { border-top: none; }
.mode-row td {
  padding: 5px 8px 5px 0;
  border-top: 1px solid var(--sep);
  vertical-align: middle;
  line-height: 1.4;
}
.mode-row:last-child td { border-bottom: 1px solid var(--sep); }
.mode-flower { width: 24px; padding-right: 10px !important; }
.mode-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-dim);
  white-space: nowrap;
}
.mode-steps {
  font-family: monospace;
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  white-space: nowrap;
}
.mode-char {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
}
.mode-row--known .mode-name  { color: var(--text-faint); font-weight: 400; }
.mode-row--known .mode-steps { color: var(--text-faint); }
.mode-row--known .mode-char  { color: var(--text-faint); }
.mode-row--focus .mode-name  { color: var(--text); font-weight: 600; }
.mode-row--focus .mode-steps { color: var(--text); }
.mode-row--focus .mode-char  { color: var(--text-dim); }

/* ── Next story guide card (bottom of story pages) ─────────────────────── */
.story-next-wrap {
  padding-top: 32px;
}
.story-next-label {
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 12px;
}
.story-next-card {
  display: flex; align-items: center;
  padding: 22px 0;
  text-decoration: none; color: inherit; cursor: pointer;
  border-top: 1px solid var(--sep);
  border-bottom: 1px solid var(--sep);
  transition: padding-left 0.22s ease;
}
.story-next-card:hover { padding-left: 8px; }
.story-next-card .s-content { flex: 1; min-width: 0; }
.story-next-card .s-label {
  display: block; font-size: 10px; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 5px;
}
.story-next-card .s-why {
  font-family: var(--font-serif); font-size: 14.5px; font-weight: 400;
  line-height: 1.42; color: var(--text); margin-bottom: 4px;
  transition: color 0.2s;
}
.story-next-card:hover .s-why { color: var(--accent); }
.story-next-card .s-what { font-size: 11.5px; color: var(--text-faint); line-height: 1.4; }
.story-next-visual { flex-shrink: 0; margin-left: 20px; }
.story-next-card.coming-soon { opacity: 0.45; cursor: default; pointer-events: none; }

/* ── Concept cross-references (concepts.js: ref / learnLater / recall) ──────── */
/* A plain link in guide prose (the outros' "its own page" tool links, M17)
   wears the same style, never the browser's default blue. */
.concept-ref,
.sec-body a:not([class]), .expand-body a:not([class]), .landing-section a:not([class]) {
  color: var(--accent); text-decoration: none;
  border-bottom: 1px dotted var(--accent);
  cursor: pointer; transition: border-bottom-color 0.15s, opacity 0.15s;
}
.concept-ref:hover,
.sec-body a:not([class]):hover, .expand-body a:not([class]):hover,
.landing-section a:not([class]):hover { border-bottom-style: solid; }
/* recall (--back) / learnLater (--fwd) render EXACTLY like ref — no arrow glyphs
   (owner, 2026-07-14). The classes stay on the markup for semantics/audit only. */
.ref-note { color: var(--text-faint); font-style: italic; }
.ref-note .concept-ref { font-style: normal; }

/* ── Harmonic-series table (flower guide) — v/^ expand to 20 partials ───────── */
.harmonic-table { width: 100%; border-collapse: collapse; margin: 12px 0 4px; font-size: 0.88em; }
.harmonic-table th, .harmonic-table td { padding: 2px 14px 3px 0; text-align: left; }
.harmonic-table th:last-child, .harmonic-table td:last-child { padding-right: 0; text-align: right; }
.harmonic-table .harm-head { opacity: 0.5; }
.harmonic-table .harm-head th { font-weight: 500; }
.harmonic-table sup { font-size: 0.7em; }
.harmonic-table td:nth-child(3) { opacity: 0.65; }
.harmonic-table td:nth-child(4) { opacity: 0.55; }
.harmonic-table .harm-extra { display: none; }
.harmonic-table.expanded .harm-extra { display: table-row; }
/* toggle row spans all columns; keep its button left-aligned */
.harmonic-table .harm-toggle-row td { text-align: left; padding-top: 6px; }
.harm-foot { font-size: 0.8em; opacity: 0.7; margin: 0 0 12px; }
.harm-toggle {
  background: none; border: 1px solid var(--sep); border-radius: 4px;
  cursor: pointer; color: var(--text-dim); font-size: 11px; line-height: 1;
  padding: 2px 9px; transition: border-color .15s, color .15s;
}
.harm-toggle:hover { border-color: #ccc8c0; color: var(--text); }

/* Per-row listen control — solos that partial through the lab voice (§2b). */
.harmonic-table td.harm-n span { vertical-align: middle; }
.harm-listen {
  width: 18px; height: 18px; border-radius: 50%;
  border: 1px solid var(--sep); background: none; cursor: pointer;
  font-size: 8px; line-height: 1; color: var(--text-dim);
  padding: 0; margin-right: 7px; vertical-align: middle;
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.harm-listen:hover { border-color: var(--accent); color: var(--accent); }
.harm-listen.on { background: var(--accent); border-color: var(--accent); color: #fff; }

/* ── Prose controls for the Harmonic Explorer (Foundation, M8a) ────────────── */
/* ⟨Try⟩ buttons inline in the sentences (the widget's .hx-preset look, from
   shared.css) and the "touch, don't press" drawing as a figure. */
.fof-try { vertical-align: baseline; margin: 0 1px; }
.fof-try-row { display: flex; flex-wrap: wrap; gap: 6px 8px; margin: -6px 0 16px; }
.fof-touch-hint { margin: 10px 0 14px; max-width: 300px; color: var(--text-dim); }
.fof-touch-hint svg { width: 100%; height: auto; display: block; }
.fof-touch-hint figcaption { font-size: 0.8em; line-height: 1.5; margin-top: 4px; }

/* ── Phone layout mode (PH1, 2026-10-05): the desktop page, stacked ──────────
   Under 700 px in portrait the two columns stack: the text column is the top
   of the viewport and scrolls with the page, as on a laptop; the visual panel
   is pinned to the bottom --viz-h of the viewport. Everything else (the strip
   engine, the page's own viz, the neck) runs unchanged; only the geometry
   moves. The reference is demos/phone-lab.html?app=c (M28 answer C, owner
   decision 2026-10-01). Scripts never test the width themselves: story-base
   reads the --story-stacked marker this block sets on #columns, so the query
   lives here alone.
   The owner's two trials from the phone round: no hard line between text and
   panel (the text fades into paper over --fade-h above the panel, drawn by
   #columns::after under the panel), and a taller text area on the landing:
   the panel never resizes, but while body.hero-bleed is on (story-base's hero
   release, off on the first scroll) the panel's top band is masked to 8 %
   (a hint of the visual under the text) and the text line sits --viz-h-hero
   up instead of --viz-h; the band closes over 0.6 s on release. Registered
   properties let the mask animate (Chrome, Safari 16.4+; older browsers snap). */
@property --band { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --dim  { syntax: '<number>'; inherits: false; initial-value: 1; }

@media (max-width: 699px) and (orientation: portrait) {
  :root { --viz-h: 46vh; --viz-h-hero: 34vh; --fade-h: 72px; }
  #columns { --story-stacked: 1; display: block; margin-top: var(--header-h); }
  #left { padding: 18px 16px calc(var(--viz-h) + 60px); }
  #right {
    position: fixed; top: auto; bottom: 0; left: 0; right: 0;
    width: 100%; margin: 0; height: var(--viz-h);
    border-left: 0; background: var(--bg); z-index: 5;
    --band: 0px; --dim: 1;
    transition: --band 0.6s cubic-bezier(0.25,0.1,0.25,1), --dim 0.6s cubic-bezier(0.25,0.1,0.25,1);
    -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,var(--dim)) 0, rgba(0,0,0,var(--dim)) var(--band), #000 calc(var(--band) + 22px));
            mask-image: linear-gradient(to bottom, rgba(0,0,0,var(--dim)) 0, rgba(0,0,0,var(--dim)) var(--band), #000 calc(var(--band) + 22px));
  }
  body.hero-bleed #right {
    width: 100%; margin-left: 0; border-left-color: var(--sep);
    --band: calc(var(--viz-h) - var(--viz-h-hero)); --dim: 0.08;
  }
  /* The text's fade into paper, ending at the text line, and below it a paper
     apron under the panel that runs 200 px past the viewport's bottom (PH1 b
     pass, owner on the phone 2026-10-07): a phone browser's bottom bar grows
     and shrinks, and while the fixed panel re-anchors a line of text showed
     beneath it. The apron sits under the panel (z 4 against 5), so in the
     hero state the band still shows the text through the panel's 8 %. */
  #columns::after {
    content: ''; position: fixed; left: 0; right: 0; bottom: -200px;
    height: calc(var(--viz-h) + var(--fade-h) + 200px);
    z-index: 4; pointer-events: none;
    background: linear-gradient(to bottom, transparent, var(--bg) var(--fade-h));
    transition: height 0.6s cubic-bezier(0.25,0.1,0.25,1);
  }
  body.hero-bleed #columns::after { height: calc(var(--viz-h-hero) + var(--fade-h) + 200px); }
  /* The landing fills the viewport below the header (less the column's own
     top padding), so the first section's top starts just under the viewport's
     bottom and story-base's hero release (that top at 99 % of the viewport)
     waits for a real scroll of ~17 px; the landing's lower part sits under the
     hero-height panel band, which hides nothing of its text. */
  .story-landing { min-height: calc(100vh - var(--header-h) - 10px); padding: 8px 0 40px; }
  .story-landing::before { inset: -20px -16px; }
  .story-landing-title { font-size: 26px; }
  .text-section { margin-bottom: 34vh; }
  .scroll-hint {
    bottom: calc(var(--viz-h) + 8px); left: 50%; transform: translateX(-50%); align-items: center; z-index: 7;
    transition: bottom 0.6s cubic-bezier(0.25,0.1,0.25,1), opacity 0.5s ease;
  }
  body.hero-bleed .scroll-hint { bottom: calc(var(--viz-h-hero) + 8px); }
  /* The neck is the bottom band of the panel, the panel's full width (the
     drawn neck is the phone default, header.js; its letters grow, story-base). */
  /* 118 px: the drawn neck at the panel's width is 115 px tall (its viewBox is
     926 × 282), and the 3D slab needs ~100 (Foundation's sizeNeck rule); the
     band was 150 until the PH2 b pass, 35 px of it empty above the neck. */
  #right .story-neck { top: auto; bottom: 2px; left: 0; right: 0; height: 118px; }
  #right #story-neck.svg-neck { left: 6px; right: 6px; height: 118px; min-height: 0; max-height: none; aspect-ratio: auto; }
  /* The strips without the flower field (PH2, owner on the phone 2026-10-07:
     the field crowded a 388 px panel). The field is the landing's hero only:
     it fades out as the hero releases on the first scroll and back in on the
     landing (b pass, 2026-10-09); hidden, FieldViz skips its frames. Each
     strip scales as one, by the --strip-scale the engine sets from
     story-base's fit (the row across the panel's width, the most strips
     above the neck); the row is only as wide as its content: the label column
     is the guide's widest label (--strip-label-w, the engine's measure). */
  #right .scales-viz { transition: opacity 0.5s ease, visibility 0s; }
  body:not(.hero-bleed) #right .scales-viz {
    opacity: 0; visibility: hidden; transition: opacity 0.5s ease, visibility 0s linear 0.5s;
  }
  #right .strip-item {
    width: var(--strip-w, 600px); max-width: none;
    transform: translateX(-50%) scale(var(--strip-scale, 1)); transform-origin: 50% 0;
  }
  #right .strip-label { width: var(--strip-label-w, 130px); }
  #right .strip { flex: none; }
  /* Diatonic's family map docks at the panel's top, scaled as one to the
     panel's width by the page's --fm-scale; the page starts each section's
     strips below its rows (PH2). On the landing it sits in the hero band's
     open lower part. */
  #right #family-map { transition: opacity .4s ease, top .4s ease, transform .4s ease; }
  #right #family-map.fm-band { top: 8px; transform: scale(var(--fm-scale, 1)); transform-origin: 50% 0; }
  #right #family-map.fm-hero { top: 58%; transform: translateY(-50%) scale(var(--fm-scale, 1)); }
  /* An embedded tool (the outro's Ear Trainer; Foundation's Explorer and the
     Position Explorer in PH2) keeps its full edges: the panel is the viewport's
     width, so the gap to the panel's sides is the only bleed an embed may
     take (⑥, M29): nothing inside may run past --story-embed-gap. */
  #right .story-embed { --story-embed-gap: 12px; padding: 10px var(--story-embed-gap); align-items: flex-start; overflow-x: hidden; }
  #right .story-embed > * { max-width: none; }
  /* The Studio (Diatonic's progressions) is one column under 1080 px; a bare
     1fr would not shrink below its widest row and ran the tool past the gap. */
  #right .story-embed .studio { grid-template-columns: minmax(0, 1fr); }
}
