/* The sounds page. styles.css supplies the palette, the top bar and .card;
   everything here is the chart, and every class is prefixed sc- so nothing
   collides with the app's own sheet.

   Two rules govern the whole thing.

   1. A symbol you can hear must look like a button. The old version drew
      chips that were buttons and did not look like buttons, and the first
      thing anyone said about it was that the sounds were not interactive.
      So: a raised face, a border, a pressed state, and a speaker mark on the
      selected one.
   2. A masked sound stays in its place, faint. The hole in a language is the
      lesson; deleting the row would hide it. */

.view{padding-bottom:9rem}

/* ---- the switch ------------------------------------------------------- */
.sc-sw{display:flex;flex-wrap:wrap;gap:.4rem;margin:.8rem 0 .2rem}
/* English, Mandarin, Cantonese, All three -- one row, always. Wrapped, the
   fourth dropped to a line of its own and the switch stopped reading as one
   choice between four. Four equal columns, and the labels shrink to fit
   rather than break. */
.sc-ctl .sc-sw:not(.sc-half){flex-wrap:nowrap;gap:.3rem}
.sc-ctl .sc-sw:not(.sc-half) .sc-lb{flex:1 1 0;min-width:0;display:block;
  text-align:center;padding:.5rem .3rem;font-size:min(.92rem,3.35vw);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sc-lb{font:inherit;font-size:.92rem;line-height:1;cursor:pointer;
  padding:.55rem .9rem;border-radius:999px;border:1px solid var(--line);
  background:var(--paper);color:var(--navy);display:flex;align-items:baseline;gap:.35rem}
.sc-lb span{font-size:.72rem;color:var(--slate)}
.sc-lb.on{background:var(--navy);border-color:var(--navy);color:#fff;font-weight:600}
.sc-lb.on span{color:rgba(255,255,255,.72)}
.sc-lb.all.on{background:var(--ink);border-color:var(--ink)}

/* ---- the control block ------------------------------------------------- */
/* Language, then half of the chart, then which kind of vowel. It sticks to
   the top of the screen because the switch a student wants is the one they
   want while they are looking at the chart, not the one they scrolled past
   three screens ago. The card's own background goes under it or the chart
   shows through. */
.sc-ctl{position:sticky;top:0;z-index:5;background:var(--card);
  margin:0 -.2rem;padding:0 .2rem .35rem;
  box-shadow:0 6px 10px -8px rgba(44,42,38,.35)}
.sc-ctl .sc-sw{margin:.5rem 0 0}

/* Two choices, so two halves: the pair reads as one switch rather than as
   two more chips in the row above. */
.sc-half{gap:0;border:1px solid var(--line);border-radius:999px;overflow:hidden}
.sc-half .sc-lb{flex:1 1 0;justify-content:center;border:0;border-radius:0;
  padding:.42rem .6rem;background:transparent}
.sc-half .sc-lb+.sc-lb{border-left:1px solid var(--line)}
.sc-half .sc-lb.on{background:var(--navy);color:#fff}
.sc-vp{border-color:#e6d3ae}
.sc-vp .sc-lb{color:var(--rust)}
.sc-vp .sc-lb+.sc-lb{border-left-color:#e6d3ae}
.sc-vp .sc-lb.on{background:var(--gold);border-color:var(--gold);color:#2c2a26}

.sc-head{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;flex-wrap:wrap}
.sc-head h1{margin:0;font-size:1.45rem}
.sc-tb{font:inherit;font-size:.82rem;white-space:nowrap;cursor:pointer;
  border:1px solid var(--line);background:var(--paper);color:var(--navy);
  border-radius:999px;padding:.35rem .9rem}
.sc-tb.on{background:var(--gold);border-color:var(--gold);color:#2c2a26;font-weight:600}
.sc-note{font-size:.9rem;color:var(--slate);line-height:1.6;margin:.7rem 0 0}
.sc-hint{font-size:.9rem;line-height:1.6;margin:.7rem 0 0}
.sc-lnk{font:inherit;font-size:.85rem;background:none;border:0;padding:0;cursor:pointer;
  color:var(--rust);border-bottom:1px solid var(--gold)}

/* ---- the consonant grid ----------------------------------------------- */
.sc-card h3{font-size:.7rem;text-transform:uppercase;letter-spacing:.08em;
  color:var(--slate);margin:0 0 .6rem}
.sc-card h3.dh{margin-top:1.3rem}
.sc-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -.3rem;padding:0 .3rem}
.sc-tab{border-collapse:collapse}
.sc-tab th{font-weight:600;color:var(--slate);font-size:.58rem;line-height:1.15;
  text-transform:uppercase;letter-spacing:.03em;text-align:center;vertical-align:bottom;
  padding:0 .2rem .4rem;max-width:4.2rem}
.sc-tab th.mn{position:sticky;left:0;z-index:2;background:var(--card);text-align:right;
  vertical-align:middle;white-space:nowrap;font-size:.66rem;text-transform:none;
  letter-spacing:0;padding:.25rem .55rem .25rem 0}
.sc-tab td{border-left:1px solid var(--line);padding:.12rem .18rem;text-align:center}
.sc-tab tbody tr+tr td,.sc-tab tbody tr+tr th.mn{border-top:1px solid var(--line)}

/* ---- a sound you can press -------------------------------------------- */
.sc-c{font:inherit;font-size:1.1rem;line-height:1;min-width:2.1rem;margin:.14rem;
  padding:.42rem .32rem .34rem;cursor:pointer;position:relative;
  border:1px solid var(--line);border-bottom-width:2px;border-radius:9px;
  background:var(--paper);color:var(--slate)}
.sc-c.on{background:#fff;border-color:#b9c6d2;border-bottom-color:var(--navy);color:var(--navy);font-weight:600}
.sc-c.var{background:#fff;border-color:#e6d3ae;border-bottom-color:var(--gold);color:var(--rust);font-weight:600}
.sc-c.off{background:transparent;border-color:transparent;color:var(--slate);opacity:.32;
  font-weight:400;cursor:default}
.sc-c.q{background:var(--gold);border-color:var(--gold);border-bottom-color:#8a6420;color:#2c2a26;font-weight:700}
.sc-c.sel{outline:2px solid var(--rust);outline-offset:1px}
.sc-c:active{transform:translateY(1px);border-bottom-width:1px;margin-bottom:calc(.14rem + 1px)}
.sc-c.mute{border-bottom-style:dotted}

/* Which languages have it, in "all three" mode. Three fixed slots, so the
   marks line up down a column and a gap is as readable as a dot. */
.sc-dots{display:flex;justify-content:center;gap:2.5px;margin-top:.26rem;height:5px}
.sc-dots i{width:5px;height:5px;border-radius:50%;background:transparent}
.sc-dots i.en{background:var(--navy)} .sc-dots i.cmn{background:var(--rust)}
.sc-dots i.yue{background:var(--green)}
.sc-dots i.v{opacity:.4}
.sc-key{display:flex;flex-wrap:wrap;gap:.9rem;font-size:.76rem;color:var(--slate);margin:.7rem 0 0}
.sc-key b{font-weight:600}
.sc-key i{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:.3rem}
.sc-key i.en{background:var(--navy)} .sc-key i.cmn{background:var(--rust)}
.sc-key i.yue{background:var(--green)}

/* ---- features ---------------------------------------------------------- */
/* Small, quiet, and many: this is a row of adjectives, not a row of buttons,
   and it must not compete with the table it filters. It only earns colour once
   it is doing something. */
.sc-feats{display:flex;flex-wrap:wrap;gap:.3rem;margin:0 0 .5rem}
.sc-ft{font:inherit;font-size:.72rem;line-height:1;cursor:pointer;
  padding:.34rem .55rem;border-radius:999px;border:1px solid var(--line);
  background:var(--paper);color:var(--slate);white-space:nowrap}
.sc-ft.on{background:var(--navy);border-color:var(--navy);color:#fff;font-weight:600}
.sc-ft.no{background:var(--rust);border-color:var(--rust);color:#fff;font-weight:600}
.sc-fhint{font-size:.8rem;color:var(--slate);margin:0 0 .7rem}
.sc-fhint b{color:var(--navy);font-weight:600}

/* A sound the filter excludes. Faded, never removed: the whole argument of
   this page is that a sound stays in its place so the gap can be seen, and a
   filter that deleted rows would be making the opposite argument. */
.sc-c.dim{opacity:.16}
.sc-c.cmp{outline:2px dashed var(--navy);outline-offset:1px}

/* ---- two sounds side by side ------------------------------------------- */
.sc-cmprow{display:flex;align-items:baseline;gap:.6rem;font-size:1.7rem;
  color:var(--navy);line-height:1.1;margin-bottom:.35rem}
.sc-cmprow span{font-size:.78rem;color:var(--slate);text-transform:uppercase;letter-spacing:.06em}
.sc-diff{margin:.25rem 0 .4rem;padding-left:1.1rem}
.sc-diff li{font-size:.88rem;line-height:1.55;margin:.1rem 0}
.sc-diff li b{color:var(--navy);font-weight:600;margin-right:.25rem}
.sc-diff li .v{color:var(--slate);font-size:.78rem;padding:0 .1rem}
.sc-pair{font-size:.86rem;line-height:1.6;margin:.45rem 0 .2rem;
  border-left:2px solid var(--gold);padding-left:.6rem;color:var(--ink)}
.sc-hold{font-size:.84rem;color:var(--rust);margin:.4rem 0 0}
.sc-cmpplay{display:flex;flex-wrap:wrap;gap:.4rem}
.sc-cmpplay .sc-plays{margin:.4rem 0 .1rem}

/* ---- vowels ------------------------------------------------------------ */
.sc-quad{display:block;width:100%;max-width:31rem;height:auto;margin:.3rem auto .4rem;overflow:visible}
.qgrid path{fill:none;stroke:var(--line);stroke-width:.8}
.qgrid line{stroke:var(--line);stroke-width:.5}
.qax text{font-size:3.6px;fill:var(--slate);letter-spacing:.05px}
.qv{cursor:pointer}
.qv text{font-size:6.4px;fill:var(--slate);opacity:.38}
.qv circle{fill:var(--slate);opacity:.32}
.qv.on text{fill:var(--navy);font-weight:700;opacity:1}
.qv.on circle{fill:var(--navy);opacity:1}
.qv.var text{fill:var(--rust);font-weight:700;opacity:1}
.qv.var circle{fill:var(--gold);opacity:1}
.qv.q text{fill:#2c2a26;font-weight:700;opacity:1}
.qv.q circle{fill:var(--gold);opacity:1}
.qv.sel circle{fill:var(--rust);opacity:1}
.qv.sel text{fill:var(--rust);opacity:1;font-weight:700}

/* ---- a glide drawn on the chart ---------------------------------------- */
/* A diphthong is one vowel moving to an approximant, so it is one arrow from
   where the mouth starts to where it is heading. The arrow stops short of the
   target point: the mouth does not arrive, and drawing it arriving is the
   error the arrow is there to prevent. The hit line is fat and invisible,
   because an arrow is 0.7px wide and a thumb is not. */
/* Paths, not lines: the arrows bow now. fill:none matters more than it looks
   -- an unfilled quadratic is a curve, a filled one is a lens. */
.qarr path{stroke-width:.7;stroke-linecap:round;fill:none}
.qarr polygon{stroke:none}
.ga{cursor:pointer}
.ga.en path{stroke:var(--navy)} .ga.en polygon{fill:var(--navy)}
.ga.cmn path{stroke:var(--rust)} .ga.cmn polygon{fill:var(--rust)}
.ga.yue path{stroke:var(--green)} .ga.yue polygon{fill:var(--green)}
.ga.sel path{stroke:var(--rust);stroke-width:1.2}
.ga.sel polygon{fill:var(--rust)}
/* Last, and one class deeper than every colour rule above, or the colour wins
   on equal specificity and paints the 5px touch target navy. */
.qarr .ga path.hit{stroke:transparent;stroke-width:9;fill:none;
  pointer-events:stroke}

.sc-dnote{margin:.1rem 0 .6rem}
.sc-dnote b{font-weight:600;color:var(--navy)}
.sc-card h3.dh2{margin-top:1rem;text-transform:none;letter-spacing:0;font-size:.8rem}
.sc-dips{display:flex;flex-wrap:wrap;gap:.3rem}
.sc-d{font:inherit;font-size:1.05rem;line-height:1.15;cursor:pointer;text-align:left;
  display:inline-flex;flex-direction:column;gap:.12rem;
  padding:.42rem .6rem .36rem;border:1px solid #b9c6d2;border-bottom-width:2px;
  border-bottom-color:var(--navy);border-radius:9px;background:#fff;color:var(--navy);font-weight:600}
.sc-d.var{border-color:#e6d3ae;border-bottom-color:var(--gold);color:var(--rust)}
.sc-d.sel{outline:2px solid var(--rust);outline-offset:1px}
.sc-d:active{transform:translateY(1px)}
.sc-d em{font-style:normal;font-size:.68rem;font-weight:400;color:var(--slate)}

/* ---- the panel --------------------------------------------------------- */
/* It sits at the foot and stays there, so two sounds can be compared by
   tapping one and then the other without anything closing. */
.sc-det{position:fixed;left:.5rem;right:.5rem;z-index:6;
  bottom:calc(.5rem + env(safe-area-inset-bottom,0px));
  max-width:44rem;margin:0 auto;padding:.65rem .85rem;
  border:1px solid var(--line);border-radius:14px;background:var(--card);
  box-shadow:0 8px 26px rgba(44,42,38,.20);max-height:46vh;overflow-y:auto}
.sc-det p{margin:0 0 .25rem;font-size:.88rem;line-height:1.5}
.sc-det p:last-child{margin-bottom:0}
.sc-row{display:flex;gap:.7rem;align-items:flex-start}
.sc-sym{flex:0 0 auto;min-width:2.6rem;text-align:center;font-size:1.9rem;line-height:1.15;color:var(--navy)}
.sc-sym.off{color:var(--slate);opacity:.45}
.sc-sym.var{color:var(--rust)}
.sc-tx{min-width:0;flex:1}
.sc-n{font-size:.74rem;color:var(--slate);text-transform:uppercase;letter-spacing:.05em}
.sc-w{font-size:1rem}
.sc-w .g{color:var(--slate)}
.sc-off{color:var(--rust)}
.sc-also{font-size:.8rem;color:var(--slate)}

/* The two play buttons. Big enough for a thumb on a train. */
.sc-plays{display:flex;flex-wrap:wrap;gap:.4rem;margin:.5rem 0 .1rem}
.sc-play{font:inherit;font-size:.86rem;cursor:pointer;display:inline-flex;align-items:center;gap:.4rem;
  padding:.44rem .8rem;border-radius:999px;border:1px solid var(--navy);
  background:var(--navy);color:#fff}
.sc-play.alt{background:var(--paper);color:var(--navy)}
.sc-play[disabled]{opacity:.4;cursor:default}
.sc-play.playing{background:var(--gold);border-color:var(--gold);color:#2c2a26}
.sc-play b{font-weight:600}
.sc-play .tts{font-size:.7rem;opacity:.75}

/* one line per language, in "all three" */
.sc-lang{border-top:1px solid var(--line);padding-top:.5rem;margin-top:.5rem}
.sc-lang:first-of-type{border-top:0;padding-top:0;margin-top:.3rem}
.sc-tag{display:inline-block;font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;
  padding:.1rem .45rem;border-radius:999px;color:#fff;margin-right:.4rem;vertical-align:.05em}
.sc-tag.en{background:var(--navy)} .sc-tag.cmn{background:var(--rust)}
.sc-tag.yue{background:var(--green)}

.sc-rest{font-size:.86rem;color:var(--slate);line-height:1.6}
.sc-rest p{margin:0}
.sc-rest a{color:var(--rust);text-decoration:none;border-bottom:1px solid var(--gold)}

.sc-cred{font-size:.78rem;color:var(--slate);line-height:1.6}
.sc-cred details summary{cursor:pointer;color:var(--rust)}
.sc-cred ul{margin:.5rem 0 0 1rem;columns:2;column-gap:1.4rem}
.sc-cred li{margin:.1rem 0;font-size:.72rem;break-inside:avoid}

/* three language marks under a vowel point, same code as the consonant dots */
.qd circle{stroke:none}
.qd circle.no{fill:none}
.qd circle.en{fill:#33475b} .qd circle.cmn{fill:#a0522d} .qd circle.yue{fill:#4a7c59}
.qd circle.v{opacity:.4} .qd circle.no{fill:none}

/* a language writes iː where the chart's point is i; say both */
.sc-sym .at{display:block;font-size:.58rem;letter-spacing:.03em;color:var(--slate);
  text-transform:uppercase;margin-top:.1rem}
.sc-alt{font-weight:600;color:var(--navy);margin-right:.3rem}
/* The instruction sits above the chips it is about, so it needs air under it
   rather than over it. */
.sc-fpre{margin:.8rem 0 .35rem}

/* Every column head and every row head is a term, and every term is a button.
   It must not look like a chip -- these are not filters, and a head that
   looked pressable in the chips' way had students filtering by Bilabial and
   finding nothing happened. So: the heading as it always was, with a dotted
   underline to say there is something under it. */
.sc-th{appearance:none;background:none;border:none;padding:0;margin:0;
  font:inherit;color:inherit;cursor:pointer;
  text-decoration:underline dotted;text-underline-offset:3px;
  text-decoration-color:var(--line)}
.sc-th:hover,.sc-th:active{color:var(--rust);text-decoration-color:var(--rust)}

@media (max-width:26rem){
  .sc-lb{font-size:.85rem;padding:.48rem .7rem}
  .sc-ctl .sc-sw:not(.sc-half) .sc-lb{font-size:min(.85rem,3.25vw);padding:.48rem .25rem}
  .sc-c{font-size:1rem;min-width:1.9rem;padding:.38rem .24rem .3rem}
  .sc-sym{font-size:1.6rem;min-width:2.1rem}
  .sc-cred ul{columns:1}
}

/* The vowel half of the feature filter. Same idea as .sc-c.dim on a
   consonant chip: the sound stays where it is, because the point is which
   region of the trapezoid lights up, not which dots survive. */
.qv.dim{opacity:.16}
.qv.cmp circle{stroke:var(--navy);stroke-width:.6;stroke-dasharray:1.2 1}

/* Filtered out means filtered out. The tap handler refuses these, so the
   pointer must not promise otherwise. */
.sc-c.dim{cursor:default}
.qv.dim{cursor:default}

/* ---- the two vowel charts ------------------------------------------------
   One trapezoid holding dots and bowed arrows together was unreadable. The
   split is the [gliding] feature made visible: held vowels left, moving
   vowels right, and the feature chip greys whichever pane it excludes rather
   than removing it, so the pair never jumps about under the finger. */
.sc-quads{display:flex;flex-wrap:wrap;gap:1.4rem 2rem;align-items:flex-start}
.sc-qbox{flex:1 1 300px;min-width:0}
.sc-qbox h4{margin:0 0 .2rem;font-size:.8rem;font-weight:600;color:var(--navy);
  letter-spacing:.02em}
.sc-qbox h4 span{font-weight:400;color:var(--slate);font-size:.74rem}
/* Excluded by the filter: still there, plainly not in play. */
.sc-qbox.pane-off{opacity:.3}
.sc-qbox.pane-off .sc-quad{pointer-events:none}

/* The faint vowels behind the arrows. Not tappable -- the held chart owns
   the vowels; this pane owns the movement between them. */
.qghost circle{fill:var(--line)}
.qghost text{font-size:4.2px;fill:var(--slate);opacity:.75}
.qghost{pointer-events:none}

/* Each arrow says its own name at the midpoint of its own curve. */
.qarr text{font-size:4.4px;font-weight:600;paint-order:stroke;
  stroke:var(--card);stroke-width:1.4px}
.ga.en text{fill:var(--navy)} .ga.cmn text{fill:var(--rust)}
.ga.yue text{fill:var(--green)} .ga.sel text{fill:var(--rust)}
/* Filtered out: faint, and inert, matching the dots and the chips. */
.ga.dim{opacity:.16;pointer-events:none;cursor:default}
.sc-d.dim{opacity:.28;pointer-events:none;cursor:default}

/* Where a sound may sit, as one line of chips rather than a stack of
   paragraphs. The stack was doubling the height of the panel, which made a
   panel anchored to the bottom of the screen read as something that had
   popped up in the way. Both ends carry a label: the headline word is a
   position too, and saying so is half the lesson. */
.sc-pos{display:flex;flex-wrap:wrap;gap:.3rem .55rem;align-items:center;margin:.35rem 0}
.sc-pos .pp{display:inline-flex;align-items:center;gap:.28rem}
.sc-pos .pp>i{font-style:normal;font-size:.62rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--slate)}
.sc-pos .pp .r{font-style:italic;letter-spacing:0;text-transform:none;font-size:inherit;color:inherit}
.sc-pos .pp.no{font-size:.75rem;color:var(--rust);gap:.3rem}
.sc-pos .sc-play{margin:0}
