/* Sophie Mini Apps — component vocabulary.
 *
 * One set of components across the coach, the profile and the partner pages, so
 * a control that means "primary action" or "a band" looks and behaves the same
 * on every screen. Every interactive component declares default / pressed /
 * focus / disabled, and every data component declares loading and empty.
 *
 * The signature component is .band — the IELTS 3.0-9.0 scale. Progress in this
 * product is a position on that scale, not a percentage, so bars that mean a
 * band are drawn as a measured scale with ticks, and bars that mean a
 * proportion (minutes, readiness) are drawn as .meter and never confused.
 */

/* ── App bar ────────────────────────────────────────────────────────────── */
.appbar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: var(--tap);
  margin-bottom: var(--s4);
}
.wordmark {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: var(--fs-lead);
  font-weight: 800;
  letter-spacing: -0.025em;
  margin-right: auto;
}
.wordmark em {
  font-style: normal;
  font-weight: 500;
  font-size: var(--fs-small);
  color: var(--text-2);
  letter-spacing: 0;
}
.iconbtn {
  flex: 0 0 auto;
  width: var(--tap); height: var(--tap);
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--text-2);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.iconbtn:hover { color: var(--text); }
.iconbtn:active { background: var(--surface-2); transform: scale(0.94); }

/* ── Icons ──────────────────────────────────────────────────────────────── */
.ico {
  display: inline-block;
  width: 20px; height: 20px;
  vertical-align: -0.22em;
  fill: currentColor;
  flex: 0 0 auto;
}
.ico--sm { width: 16px; height: 16px; }
.ico--lg { width: 24px; height: 24px; }
.ico--xl { width: 40px; height: 40px; }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  width: 100%;
  min-height: 50px;
  padding: 13px var(--s5);
  border: 0;
  border-radius: var(--r-btn);
  background: var(--accent);
  color: var(--on-accent);
  font-size: var(--fs-body);
  font-weight: 800;
  letter-spacing: -0.01em;
  text-align: center;
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease), opacity var(--dur-1) var(--ease),
              background var(--dur-1) var(--ease);
}
.btn + .btn { margin-top: var(--s2); }
.btn:active { transform: scale(0.985); }
.btn:disabled { opacity: 0.45; cursor: default; transform: none; }

.btn--quiet { background: var(--surface-2); color: var(--text); }
.btn--ghost {
  background: transparent; color: var(--text-2); font-weight: 700;
  min-height: var(--tap);
}
.btn--ghost:active { background: var(--surface-2); }
.btn--danger { background: transparent; color: var(--danger-text); font-weight: 700; }
.btn--danger:active { background: var(--danger-soft); }
.btn--sm { min-height: 38px; padding: 8px var(--s4); font-size: var(--fs-small); width: auto; }

.btn-row { display: flex; gap: var(--s2); }
.btn-row .btn { margin-top: 0; }

/* A button mid-request keeps its width so the layout does not jump. */
.btn[data-busy="1"] { pointer-events: none; opacity: 0.7; }

/* ── Bottom dock (thumb-zone actions) ───────────────────────────────────── */
.dock {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--tabbar-h) + var(--safe-b));
  z-index: 20;
  padding: var(--s3) var(--s4) var(--s4);
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.dock-inner { max-width: var(--page); margin: 0 auto; }
.dock .btn { margin-top: 0; }
.dock .btn + .btn { margin-top: var(--s2); }

/* ── Cards ──────────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: var(--card-border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
  padding: var(--s4);
}
.card + .card { margin-top: var(--s3); }
.card--flush { padding: var(--s2) var(--s4); }
.card--plain { background: transparent; border: 0; box-shadow: none; padding: 0; }

.section {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  margin: var(--s6) 0 var(--s2);
}
.section h2 { font-size: var(--fs-lead); }
.section .section-meta { margin-left: auto; color: var(--text-2); font-size: var(--fs-small); }
.view > .section:first-child { margin-top: var(--s2); }

/* A line of scale under a section heading: what the numbers in the card below
   are measured on. Pulls up over the heading's own bottom margin so it reads as
   part of the header rather than as the first item of the list. */
.section-note {
  margin: calc(var(--s2) * -1) 0 var(--s2);
  color: var(--text-2);
  font-size: var(--fs-small);
}

/* ── List rows ──────────────────────────────────────────────────────────── */
.rows > .row + .row { border-top: 1px solid var(--line); }
.row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: var(--tap);
  padding: var(--s3) 0;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  color: inherit;
}
button.row { cursor: pointer; border-radius: var(--r-sm); }
button.row:active { background: var(--surface-2); }
.row-ico {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-2);
}
.row-ico--accent { background: var(--accent-soft); color: var(--accent-text); }
.row-ico--good { background: var(--good-soft); color: var(--good-text); }
/* These are spans so a whole row can be a <button>; they still have to stack,
   or a title and its subtitle run together on one line. */
.row-main { flex: 1 1 auto; min-width: 0; display: block; }
.row-title { display: block; font-weight: 700; letter-spacing: -0.01em; }
.row-sub { display: block; color: var(--text-2); font-size: var(--fs-small); margin-top: 1px; }
.row-meta {
  flex: 0 0 auto;
  color: var(--text-2);
  font-size: var(--fs-small);
  font-weight: 700;
  text-align: right;
}
.row-go { flex: 0 0 auto; color: var(--text-3); }

/* ── Chips ──────────────────────────────────────────────────────────────── */
.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-small);
  font-weight: 700;
  cursor: default;
}
button.chip { cursor: pointer; transition: transform var(--dur-1) var(--ease); }
button.chip:active { transform: scale(0.96); }
.chip--on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.chip--accent { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
.chip--good { background: var(--good-soft); border-color: transparent; color: var(--good-text); }
.chip--gold { background: var(--gold-soft); border-color: transparent; color: var(--gold); }
.chip--quiet { background: var(--surface-2); border-color: transparent; color: var(--text-2); }

/* ── The band scale (signature) ─────────────────────────────────────────── */
/* 3.0-9.0 mapped across the track, ticks at every whole band. A width here is
   a position on the IELTS scale and nothing else. */
.band { width: 100%; }
.band-track {
  position: relative;
  height: 10px;
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
}
.band-fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0;
  border-radius: var(--r-pill);
  background: var(--accent);
  transition: width var(--dur-4) var(--ease);
}
.band-fill--good { background: var(--good); }
.band-tick {
  position: absolute;
  top: 0; bottom: 0;
  width: 1px;
  margin-left: -0.5px;
  background: var(--bg);
  opacity: 0.55;
}
.band-goal {
  position: absolute;
  top: -3px; bottom: -3px;
  width: 3px;
  margin-left: -1.5px;
  border-radius: 2px;
  background: var(--text);
}
.band--sm .band-track { height: 6px; }
.band--sm .band-goal { top: -2px; bottom: -2px; width: 2px; }
.band--hero .band-track { height: 14px; }

.band-legend {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  margin-top: var(--s2);
  font-size: var(--fs-tiny);
  color: var(--text-2);
}
.band-legend .spacer { margin-left: auto; }

.band-num {
  font-family: var(--font-num);
  font-size: var(--fs-band);
  font-weight: 800;
  line-height: 1;
  letter-spacing: var(--tr-display);
}
.band-num--hero { font-size: var(--fs-band-hero); }
.band-num small {
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--text-2);
  letter-spacing: 0;
}

/* ── Meter (a genuine proportion: minutes, readiness, step progress) ────── */
.meter {
  position: relative;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
}
.meter > span {
  display: block;
  height: 100%;
  width: 0;
  border-radius: var(--r-pill);
  background: var(--accent);
  transition: width var(--dur-3) var(--ease);
}
.meter--good > span { background: var(--good); }

/* ── Stats ──────────────────────────────────────────────────────────────── */
.stats { display: flex; gap: var(--s2); }
.stat {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--s3) var(--s2);
  border-radius: var(--r-card);
  background: var(--surface);
  border: var(--card-border);
  box-shadow: var(--shadow);
  text-align: center;
}
.stat-v {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  font-size: var(--fs-title);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: var(--tr-title);
}
.stat-v .ico { color: var(--accent-text); }
.stat-l {
  margin-top: 3px;
  font-size: var(--fs-micro);
  color: var(--text-2);
  font-weight: 600;
}

/* ── Steps (today's plan / session position) ────────────────────────────── */
.steps { position: relative; }
.step {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) 0;
  position: relative;
}
.step + .step { border-top: 1px solid var(--line); }
.step-mark {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: var(--fs-tiny);
  font-weight: 800;
}
.step--done .step-mark { background: var(--good); color: var(--on-accent); }
.step--current .step-mark { background: var(--accent); color: var(--on-accent); }
.step--skipped .step-mark { background: transparent; box-shadow: inset 0 0 0 1px var(--line-strong); }
.step-name { flex: 1 1 auto; font-weight: 700; letter-spacing: -0.01em; }
.step--done .step-name, .step--skipped .step-name { color: var(--text-2); font-weight: 600; }
.step-len { flex: 0 0 auto; color: var(--text-3); font-size: var(--fs-small); font-weight: 700; }

/* Beat position: one pip per beat in the current step. */
.pips { display: flex; gap: 4px; }
.pip { width: 16px; height: 3px; border-radius: 2px; background: var(--track); }
.pip--on { background: var(--accent); }

/* ── Recorder ───────────────────────────────────────────────────────────── */
.rec { text-align: center; }
.rec-status {
  min-height: 20px;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--text-2);
}
.rec-status.danger-text { color: var(--danger-text); }
.rec-timer {
  min-height: 26px;
  font-family: var(--font-num);
  font-size: var(--fs-title);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: var(--tr-title);
}
.rec-timer.over { color: var(--danger-text); }

.rec-stage {
  position: relative;
  width: 92px; height: 92px;
  margin: var(--s2) auto 0;
}
/* The ring is the input level: it answers "is the mic actually hearing me?".
   ui.js scales it from the analyser; it is never decorative. */
.rec-ring {
  position: absolute;
  left: 50%; top: 50%;
  width: 76px; height: 76px;
  margin: -38px 0 0 -38px;
  border-radius: var(--r-pill);
  background: var(--danger-soft);
  transform: scale(1);
  transition: transform 80ms linear;
  pointer-events: none;
}
.rec-btn {
  position: absolute;
  left: 50%; top: 50%;
  width: 76px; height: 76px;
  margin: -38px 0 0 -38px;
  display: flex; align-items: center; justify-content: center;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease), background var(--dur-2) var(--ease);
}
.rec-btn .ico { width: 30px; height: 30px; }
.rec-btn:active { transform: scale(0.94); }
.rec-btn:disabled { opacity: 0.5; }
.rec-btn.recording { background: var(--danger); color: var(--on-danger); }
.rec-btn.recording .stop-glyph {
  display: block; width: 22px; height: 22px; border-radius: 5px; background: currentColor;
}
.rec-actions:empty { display: none; }
.rec-actions { margin-top: var(--s3); }

/* ── Prose (feedback, model answers, analysis: the Read surfaces) ───────── */
.prose {
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  max-width: 68ch;
}
.prose b { font-weight: 800; }
.prose code {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  white-space: nowrap;
}
.prose h4 { margin: var(--s4) 0 var(--s1); font-size: var(--fs-small); color: var(--text-2); }
.prose-pre { white-space: pre-wrap; }

details.disclose { margin-top: var(--s3); border-top: 1px solid var(--line); padding-top: var(--s3); }
details.disclose > summary {
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--text-2);
}
details.disclose > summary::-webkit-details-marker { display: none; }
details.disclose > p { margin-top: var(--s2); color: var(--text-2); font-size: var(--fs-small); }

/* ── Notes, locks, empties ──────────────────────────────────────────────── */
.note {
  display: flex; gap: var(--s2);
  padding: var(--s3);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: var(--fs-small);
}
.note--danger { background: var(--danger-soft); color: var(--danger-text); }
.note .ico { color: inherit; }

.lock { text-align: center; }
.lock-ico {
  width: 46px; height: 46px;
  margin: 0 auto var(--s3);
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill);
  background: var(--gold-soft);
  color: var(--gold);
}
/* What is locked is shown, not described: the real rows, unreadable. */
.lock-peek { position: relative; margin-bottom: var(--s4); }
.lock-peek > .lock-peek-body {
  filter: blur(5px);
  opacity: 0.5;
  pointer-events: none;
  user-select: none;
}
.lock-peek::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0; height: 60%;
  background: linear-gradient(to bottom, rgba(0,0,0,0), var(--surface));
}

.empty { text-align: center; padding: var(--s8) var(--s5); }
.empty .ico { color: var(--text-3); }
.empty-title { margin: var(--s3) 0 var(--s1); font-size: var(--fs-lead); font-weight: 800; }
.empty-sub { color: var(--text-2); font-size: var(--fs-small); margin-bottom: var(--s4); }

/* ── Loading ────────────────────────────────────────────────────────────── */
/* Skeletons are shaped like what is coming, so the page does not reflow when
   the data lands. */
.skel {
  border-radius: var(--r-sm);
  background: var(--skeleton);
  animation: skel 1.2s ease-in-out infinite;
}
@keyframes skel { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
.skel--card { height: 84px; border-radius: var(--r-card); }
.skel--line { height: 12px; }
.skel + .skel { margin-top: var(--s3); }

.spinner {
  width: 24px; height: 24px;
  margin: var(--s5) auto;
  border: 2.5px solid var(--track);
  border-top-color: var(--accent);
  border-radius: var(--r-pill);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Form controls ──────────────────────────────────────────────────────── */
.field { display: block; }
.field + .field { margin-top: var(--s4); }
.field-label { display: block; font-size: var(--fs-small); font-weight: 700; color: var(--text-2); margin-bottom: 6px; }

.input, .select {
  width: 100%;
  min-height: var(--tap);
  padding: 11px var(--s3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-body);
  -webkit-appearance: none;
  appearance: none;
}
textarea.input { min-height: 88px; resize: vertical; line-height: var(--lh-body); }
.input::placeholder { color: var(--text-3); }
.input:focus-visible, .select:focus-visible { border-color: var(--accent); }
.select {
  padding-right: var(--s7);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23808c9c' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s3) center;
  background-size: 16px 16px;
}
.select--inline { width: auto; min-width: 116px; }

.switch { position: relative; flex: 0 0 auto; width: 48px; height: 28px; }
.switch input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.switch-track {
  position: absolute; inset: 0;
  border-radius: var(--r-pill);
  background: var(--track);
  transition: background var(--dur-2) var(--ease);
}
.switch-track::after {
  content: "";
  position: absolute; top: 3px; left: 3px;
  width: 22px; height: 22px;
  border-radius: var(--r-pill);
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform var(--dur-2) var(--ease-spring);
}
.switch input:checked + .switch-track { background: var(--accent); }
.switch input:checked + .switch-track::after { transform: translateX(20px); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch input:disabled + .switch-track { opacity: 0.5; }

/* ── Avatar ─────────────────────────────────────────────────────────────── */
.avatar {
  width: 72px; height: 72px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-text);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-display);
  font-weight: 800;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}
.avatar--img { color: transparent; }
.avatar--sm { width: 42px; height: 42px; font-size: var(--fs-lead); }
.avatar-wrap { position: relative; width: 72px; height: 72px; }
.avatar-edit {
  position: absolute; right: -2px; bottom: -2px;
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--bg);
  border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  cursor: pointer;
}
.avatar-edit:disabled { opacity: 0.6; }

/* ── Skill rows (a criterion or subskill on the band scale) ─────────────── */
.skill { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; }
.skill + .skill { border-top: 1px solid var(--line); }
.skill-name { flex: 1 1 auto; min-width: 0; font-weight: 700; letter-spacing: -0.01em; }
.skill-name .row-sub, .skill-name .tl-sub { font-weight: 500; }
.skill-band { flex: 0 0 96px; }
.skill-v {
  flex: 0 0 auto;
  min-width: 32px;
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}

/* ── Estimate-against-target header ─────────────────────────────────────── */
.hero-band-head {
  display: flex;
  align-items: flex-end;
  gap: var(--s3);
  margin-bottom: var(--s3);
}
.hero-band-head .band-num { color: var(--accent-text); }
.hero-band-head .target { margin-left: auto; text-align: right; }
.hero-band-head .target b { display: block; font-size: var(--fs-lead); font-weight: 800; }

/* ── Preference rows ────────────────────────────────────────────────────── */
.pref { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; min-height: var(--tap); }
.pref + .pref { border-top: 1px solid var(--line); }
.pref-main { flex: 1 1 auto; min-width: 0; }
.pref-label { display: block; font-weight: 700; letter-spacing: -0.01em; }
.pref-sub { display: block; color: var(--text-2); font-size: var(--fs-small); margin-top: 1px; }
.pref .select, .pref .input { flex: 0 0 auto; width: auto; min-width: 128px; }

/* ── Tab bar ────────────────────────────────────────────────────────────── */
.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  height: calc(var(--tabbar-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.tab {
  flex: 1 1 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  border: 0;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  transition: color var(--dur-1) var(--ease);
}
.tab-l { font-size: var(--fs-micro); font-weight: 700; }
.tab--active { color: var(--accent-text); }
.tab:active .ico { transform: scale(0.9); }
.tab .ico { transition: transform var(--dur-1) var(--ease); }

/* ── Pager ──────────────────────────────────────────────────────────────── */
.pager { display: flex; align-items: center; justify-content: space-between; margin-top: var(--s4); }
.pager span { color: var(--text-2); font-size: var(--fs-small); }

/* ── Toast ──────────────────────────────────────────────────────────────── */
.toast {
  position: fixed;
  left: 50%; bottom: calc(var(--tabbar-h) + var(--dock-h) + var(--safe-b) + var(--s4));
  z-index: 60;
  transform: translate(-50%, 12px);
  display: flex; align-items: center; gap: var(--s2);
  max-width: calc(100% - var(--s7));
  padding: 11px var(--s4);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-small);
  font-weight: 700;
  box-shadow: var(--shadow-lift);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.toast--in { opacity: 1; transform: translate(-50%, 0); }
.toast .ico { color: var(--good-text); }

/* ── Peak moments (three, and only three) ───────────────────────────────── */
.rise-in { animation: rise var(--dur-3) var(--ease) both; }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.pop-in { animation: pop var(--dur-4) var(--ease-spring) both; }
@keyframes pop { from { opacity: 0; transform: scale(0.7); } to { opacity: 1; transform: scale(1); } }

.pulse-once { animation: pulse var(--dur-4) var(--ease) 1; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 var(--accent-line); }
  100% { box-shadow: 0 0 0 14px rgba(0, 0, 0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .rise-in, .pop-in { animation: view-in 1ms both; }
  .pulse-once { animation: none; }
  .band-fill, .meter > span { transition: none; }
}
