/* App shell and the stage-A screens. Built only from the kit's tokens (tokens.css, motion.css) and on top of
   components.css; no new colours. Phone (390px) first; 900px moves the tabs into the top bar; 960px pairs Today's
   sections. Every transition here uses the motion tokens, so reduced motion covers it. */

/* ---------- shell ---------- */
.skip-link { position: absolute; inset-inline-start: 8px; top: -60px; min-height: var(--tap); box-sizing: border-box; display: inline-flex; align-items: center; z-index: var(--z-fx); padding: 10px 14px; border-radius: var(--r-ctl); background: var(--ink); color: var(--on-ink); text-decoration: none; }
.skip-link:focus { top: 8px; }
.bar-inner .tabs-top { display: none; }
.avatar-link { margin-inline-start: auto; display: grid; place-items: center; width: var(--tap); height: var(--tap); margin-inline-end: -6px; border-radius: 50%; text-decoration: none; color: var(--ink); }
.avatar-link[aria-current="page"] .avatar { box-shadow: 0 0 0 2px var(--canvas), 0 0 0 3.5px var(--accent); }
.avatar { display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--surface-2); color: var(--ink); font: 600 13px/1 var(--font-ui); letter-spacing: 0.02em; box-shadow: inset 0 0 0 1px var(--hairline); }
.icon { flex: none; }
#view { outline: none; view-transition-name: fx-view; }
#view:focus-visible { outline: none; }
#view h1:focus { outline: none; }
#view h1:focus-visible { outline: none; }
/* the boot line shows only when a load is slow: it fades in after 300 ms, so a fast load shows nothing before Today */
.boot-note { padding-top: var(--s-10); color: var(--ink-3); animation: boot-in var(--dur-base) var(--ease-out) 300ms both; }
@keyframes boot-in { from { opacity: 0; } to { opacity: 1; } }
body[data-chrome="off"] .bar, body[data-chrome="off"] #tabs-slot { display: none; }
.banner { margin: 0; padding: 8px var(--gutter); background: var(--surface-2); color: var(--ink-2); font-size: 13px; text-align: center; }
@media (min-width: 900px) {
  .bar-inner .tabs-top { display: flex; margin-inline-start: var(--s-6); align-self: stretch; align-items: stretch; }
  .bar-inner .tabs-top a { padding: 0 2px; }
  .tabs-bottom { display: none; }
}

/* ---------- shared bits ---------- */
.page-pad { padding-top: var(--s-8); }
.page-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); padding-top: var(--s-6); margin-bottom: var(--s-5); }
.section > h2 + .section-sub { margin-top: var(--s-1); }
.section > .section-sub + * { margin-top: var(--s-3); }
.ink { color: var(--ink); }
.block { display: block; }
.more { margin-top: var(--s-3); }
.lead { font: 400 19px/1.45 var(--font-display); color: var(--ink-2); }

.notice { display: flex; gap: var(--s-3); align-items: flex-start; margin-top: var(--s-4); padding: var(--s-3) var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); color: var(--ink-2); font-size: 14px; }
.notice > .icon { margin-top: 2px; color: var(--accent-ink); }
.notice-warning > .icon { color: var(--bad); }
.notice-body { display: grid; gap: 6px; min-width: 0; }
.notice-title { color: var(--ink); font-weight: 500; }
.notice-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-1); }
.notice-actions .btn { white-space: normal; text-align: center; line-height: 1.25; padding-block: 8px; }
.notice { min-width: 0; }

.list { list-style: none; margin: 0; padding: 0; }
.list-item { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-3) 0; border-bottom: 1px solid var(--hairline); }
.row { display: flex; align-items: center; gap: var(--s-3); min-height: 56px; padding: var(--s-2) 0; border-bottom: 1px solid var(--hairline); color: var(--ink); text-decoration: none; }
.row-main { display: grid; gap: 2px; flex: 1; min-width: 0; }
.row-title { font-weight: 500; }
.row-detail { font-size: 13px; color: var(--ink-3); }
.row-trail { font-size: 13px; color: var(--ink-2); white-space: nowrap; }
.row .icon, .plan-row > .icon:last-child { color: var(--ink-3); }

/* ---------- Today ---------- */
.today-hero { margin-top: 0; }
.today > .notice { margin: 0 0 var(--s-4); }
.today-a > .notice { margin-top: var(--s-4); }
.today-hero .label { color: var(--ink-2); }
.hero-count { display: flex; align-items: baseline; gap: 0.22em; margin-top: var(--s-2); }
.hero-count .unit { font-size: 32px; transform: translateY(-0.06em); }
/* the next digit's serif sits just under the odometer window at this size: a long fade at the bottom edge, and a
   short one at the top so a rolling digit never shows as a sliver above the numeral (the glyphs start about 10 %
   down the window, so only a hairline of their tops fades) */
.hero-count .odo { -webkit-mask-image: linear-gradient(transparent 0, #000 12%, #000 84%, transparent 96%); mask-image: linear-gradient(transparent 0, #000 12%, #000 84%, transparent 96%); margin-bottom: -0.1em; }
/* the countdown is the way to the date that drives it */
.hero-link { display: block; color: inherit; text-decoration: none; border-radius: var(--r-ctl); }
.hero-link:hover .hero-edit { text-decoration: underline; }
.hero-edit { color: var(--accent-ink); }
/* toasts: wrap long messages, and sit above the sticky button when there is one */
.toast { white-space: normal; width: max-content; max-width: calc(100vw - 2 * var(--gutter)); border-radius: 18px; }
:root:has(.dock) .toast { bottom: calc(150px + env(safe-area-inset-bottom)); }
@media (min-width: 900px) { :root:has(.dock) .toast { bottom: calc(32px + env(safe-area-inset-bottom)); } .toast { bottom: calc(32px + env(safe-area-inset-bottom)); } }
.hero-today { margin-top: var(--s-3); }
.hero-date { margin-top: var(--s-2); color: var(--ink-2); }
.today-hero .runway { margin-top: var(--s-6); }
.hero-days { margin-top: var(--s-5); }
.hero-foot { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); margin-top: var(--s-5); flex-wrap: wrap; }
.hero-btn { display: none; }
/* a phone: the hero leaves room for the first plan row above the sticky button */
@media (max-width: 419px) {
  .today-hero { padding: var(--s-5) var(--s-4) var(--s-4); }
  .today-hero .numeral { font-size: clamp(76px, 22vw, 104px); }
  .today-hero .runway { margin-top: var(--s-4); }
  .today-hero .runway-bar { height: calc(var(--h, 64px) * 0.62); }
  .hero-foot { margin-top: var(--s-4); }
}

/* readiness: the field */
.ready-figure { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s-1) var(--s-3); margin-top: var(--s-3); }
.today-ready .field { margin-top: var(--s-4); }
.legend span.is-empty::before { box-shadow: inset 0 0 0 1px var(--hairline-strong); }
.ready-def { margin-top: var(--s-3); max-width: var(--measure); }

/* rows that did not fit the minutes */
.plan-extra { margin-top: var(--s-5); }
.plan-extra h3 { margin-bottom: var(--s-1); }
/* "If you have time": the same row anatomy as the plan (circle, chevron), quieter: the title in ink-2 */
.plan-extra-row { min-height: 52px; }
.plan-extra-row .row-title { color: var(--ink-2); font-weight: 500; }
.plan-extra-row .plan-state { box-shadow: inset 0 0 0 1.5px var(--hairline-strong); }
.plan-extra-row:hover .row-title { color: var(--ink); }

.plan { list-style: none; margin: var(--s-3) 0 0; padding: 0; }
.plan-row { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto 16px; align-items: center; gap: var(--s-3); min-height: 60px; padding: var(--s-2) 0; border-bottom: 1px solid var(--hairline); color: var(--ink); text-decoration: none; }
.plan-state { display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--field-border); color: var(--on-ink); }
.is-done .plan-state { background: var(--ink); box-shadow: none; }
.is-done .row-title { color: var(--ink-2); }
.is-setup .plan-state { box-shadow: none; color: var(--accent-ink); }
.is-setup .row-title { color: var(--accent-ink); }
.plan-done, .plan-empty { display: flex; gap: var(--s-2); align-items: center; margin-top: var(--s-3); color: var(--ink-2); }

.mbars { list-style: none; margin: var(--s-3) 0 0; padding: 0; display: grid; gap: 2px; }
.mbar { display: grid; grid-template-columns: 88px minmax(0, 1fr) 104px; align-items: center; gap: var(--s-3); min-height: var(--tap); color: var(--ink); text-decoration: none; }
.mbar-name { font-size: 14px; font-weight: 500; }
.mbar .track { height: 6px; overflow: visible; background: var(--cell-plan); box-shadow: inset 0 0 0 1px var(--field-border); }
.mbar .track .fill { border-radius: 3px; }
.mbar .pass { position: absolute; top: -5px; bottom: -5px; inset-inline-start: var(--at); width: 2px; margin-inline-start: -1px; border-radius: 1px; background: var(--ink-3); }
.mbar-val { text-align: end; font-size: 14px; }
.mbar-val.none { color: var(--ink-3); font-size: 13px; }

.dock { position: fixed; inset-inline-start: 0; inset-inline-end: 0; bottom: calc(57px + env(safe-area-inset-bottom)); z-index: calc(var(--z-bar) - 1); padding: var(--s-3) max(var(--gutter), env(safe-area-inset-left)) var(--s-2); background: linear-gradient(to bottom, transparent, var(--canvas) 34%); }
.dock .btn { box-shadow: var(--shadow-lift); }
/* a tablet (600 to 899 px): the dock's button keeps the content's width, centred */
@media (min-width: 600px) { .dock { padding-inline: max(var(--gutter), calc((100% - 560px) / 2)); } }
.today.has-dock { padding-bottom: 76px; }
/* the sticky bars never cover what has focus or what a link scrolls to */
html { scroll-padding-top: calc(52px + env(safe-area-inset-top) + var(--s-2)); scroll-padding-bottom: calc(57px + env(safe-area-inset-bottom) + var(--s-3)); }
:root:has(.dock) { scroll-padding-bottom: calc(57px + 84px + env(safe-area-inset-bottom)); }
/* the error view: Try again and Back to Today in the dock on a phone, inline on a desktop */
.error-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.error-actions.dock .btn { flex: 1; }
@media (prefers-reduced-transparency: reduce) { .dock { background: var(--canvas); } }
@media (min-width: 900px) {
  .dock { display: none; }
  .error-actions.dock { display: flex; position: static; padding: 0; background: none; }
  .error-actions.dock .btn { flex: none; box-shadow: none; }
  .today.has-dock { padding-bottom: 0; }
  .hero-btn { display: inline-flex; }
  html, :root:has(.dock) { scroll-padding-bottom: var(--s-4); }
}
@media (min-width: 960px) {
  .today-grid { display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr); grid-template-areas: "a b" "c b"; column-gap: var(--s-12); align-items: start; }
  .today-a { grid-area: a; }
  .today-b { grid-area: b; }
  .today-c { grid-area: c; }
  .today-b > .section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
}

/* ---------- forms and settings ---------- */
.form-field { margin-top: var(--s-5); }
.field-hint { margin-top: 6px; font-size: 13px; color: var(--ink-3); max-width: var(--measure); }
.field-error { margin-top: 6px; font-size: 13px; color: var(--bad); }
.input[aria-invalid="true"] { border-color: var(--bad); }
input[type="date"].input { min-height: var(--tap); }
.seg { max-width: 100%; }
.chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.row-actions { display: flex; gap: var(--s-2); margin-top: var(--s-3); align-items: center; }
.row-actions.wrap { flex-wrap: wrap; }
.date-row { display: flex; align-items: flex-start; gap: var(--s-2); flex-wrap: wrap; }
.date-row > .btn { margin-top: calc(var(--s-5) + 22px); }
.date-row .form-field { flex: 1 1 220px; }
.derived { margin-top: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); color: var(--ink); font-size: 14px; }
.diag-details summary { cursor: pointer; min-height: var(--tap); display: flex; align-items: center; color: var(--accent-ink); font-weight: 500; }
.derived + .caption { margin-top: var(--s-2); }
.switch-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); min-height: 56px; padding: var(--s-2) 0; border-bottom: 1px solid var(--hairline); }
.switch-row:first-of-type { margin-top: var(--s-4); }
.switch-row label { display: grid; gap: 2px; cursor: pointer; }
.switch { appearance: none; -webkit-appearance: none; flex: none; position: relative; width: 46px; height: 28px; margin: 0; border-radius: var(--r-pill); background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--hairline-strong); cursor: pointer; transition: background-color var(--dur-quick) var(--ease-out); }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: var(--surface); box-shadow: 0 1px 2px rgb(0 0 0 / 0.18), 0 0 0 1px var(--hairline); transition: transform var(--dur-base) var(--spring-snappy); }
.switch:checked { background: var(--ink); box-shadow: none; }
.switch:checked::after { transform: translateX(calc(18px * max(var(--move), 1))); }
.switch:disabled { opacity: 0.45; cursor: default; }
.btn-danger { background: var(--bad); border-color: var(--bad); color: #fff; }
:root[data-theme="dark"] .btn-danger { color: var(--on-ink); }
.btn.danger { color: var(--bad); }
.btn .icon { width: 18px; height: 18px; }

.profile-head { display: flex; align-items: center; gap: var(--s-4); padding-top: var(--s-6); }
.profile-head .avatar { width: 56px; height: 56px; font-size: 20px; }
.profile-head .avatar .icon { width: 26px; height: 26px; }
.profile-head .caption { margin-top: 4px; font-size: 14px; color: var(--ink-2); }
.profile > .form-field { margin-top: var(--s-6); max-width: 420px; }
.profile .section { max-width: 760px; }
.conn { margin-top: var(--s-6); }
.conn + .conn { padding-top: var(--s-6); border-top: 1px solid var(--hairline); }
.conn h3 { margin-bottom: var(--s-1); }
.conn .status { color: var(--ink-2); }
/* Profile › Courses (features/profile/index.js): the add list opens from a 44 px summary */
.course-add > summary { min-height: 44px; padding: 10px 0; box-sizing: border-box; cursor: pointer; }

/* Profile › Data › Backup and Restore (features/profile/backup.js) */
.backup { display: grid; gap: var(--s-2); padding-top: var(--s-6); border-top: 1px solid var(--hairline); }
.backup h3 { margin-bottom: 0; }
.backup .row-actions { margin-top: var(--s-1); }
.restore { display: grid; gap: var(--s-2); margin-top: var(--s-4); }
.restore h4, .restore-panel h4 { margin: 0; font-size: 16px; }
.restore-panel { display: grid; gap: var(--s-2); padding: var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); }
.restore-panel[hidden] { display: none; }
.restore-panel p { margin: 0; }
.restore-devices { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.restore-devices li { display: grid; gap: 2px; }
.restore-device { font-weight: 600; overflow-wrap: anywhere; }
.restore-preview { display: grid; gap: var(--s-1); padding-top: var(--s-2); border-top: 1px solid var(--hairline); }
.import-summary { display: grid; gap: 6px; margin-top: var(--s-4); padding: var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); }
.confirm { margin-top: var(--s-4); padding: var(--s-4); border-radius: var(--r-ctl); box-shadow: inset 0 0 0 1px var(--bad); }
.diag { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--s-2) var(--s-5); margin: var(--s-4) 0 0; font-size: 14px; }
.diag dt { color: var(--ink-3); }
.diag dd { margin: 0; overflow-wrap: anywhere; }

/* ---------- onboarding ---------- */
.welcome { max-width: 560px; margin: 0 auto; padding: calc(var(--s-6) + env(safe-area-inset-top)) 0 var(--s-10); }
.welcome-brand { display: flex; align-items: center; gap: 10px; color: var(--ink); }
.welcome-brand svg { width: 26px; height: 26px; }
.welcome .segments { margin: var(--s-6) 0 var(--s-8); }
.welcome-step { --gap: var(--s-5); }
.choices { display: grid; gap: var(--s-2); }
.choice { display: flex; align-items: center; gap: var(--s-3); min-height: 56px; padding: var(--s-3) var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline-strong); cursor: pointer; }
.choice:has(input:checked) { box-shadow: inset 0 0 0 1.5px var(--ink); }
.choice:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.choice input { width: 18px; height: 18px; margin: 0; accent-color: var(--ink); flex: none; }
.choice-main { display: grid; gap: 2px; }
.choice-title { font-weight: 500; }
.choice-detail { font-size: 13px; color: var(--ink-3); }
.welcome-nav { position: sticky; bottom: 0; z-index: 2; display: flex; justify-content: space-between; align-items: center; gap: var(--s-2); margin-top: var(--s-8); padding: var(--s-3) 0 calc(var(--s-3) + env(safe-area-inset-bottom)); background: linear-gradient(to bottom, transparent, var(--canvas) 30%); }
@media (prefers-reduced-transparency: reduce) { .welcome-nav { background: var(--canvas); } }
.welcome .btn-primary:disabled { opacity: 0.4; }
.later { margin-top: var(--s-6); }
.later-list { list-style: none; margin: var(--s-2) 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-1) var(--s-4); color: var(--ink-3); font-size: 14px; }
.summary-runway { margin-top: var(--s-3); }
.summary-runway .runway-bar { height: calc(var(--h, 64px) * 0.6); }
.summary-days { margin-top: var(--s-3); }
.welcome-nav-end { display: flex; gap: var(--s-2); }
.summary { padding: var(--s-5); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--shadow-card); --gap: var(--s-3); }
.summary-goal { font: 400 24px/1.2 var(--font-display); text-wrap: balance; }
.summary-goal + .caption { margin-top: 4px; font-size: 13px; }
.summary-date { font-weight: 500; }
.summary-list { margin: 0; padding-inline-start: 1.2em; color: var(--ink-2); }

/* ---------- placeholders ---------- */
.placeholder { padding-top: var(--s-6); --gap: var(--s-4); max-width: 560px; }
.placeholder .btn { justify-self: start; }

/* Where you stand (features/today/standing.js): a module bar, then its practice items known and one next action */
.stand-list { gap: var(--s-3); }
.stand-row { display: grid; gap: var(--s-1); padding-bottom: var(--s-3); border-bottom: 1px solid var(--hairline); }
.stand-meta { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-2); align-items: baseline; margin: 0; }
.stand-weak { font: 600 12px/1.3 var(--font-ui); color: var(--accent-ink); }
.stand-items:empty { display: none; }
.stand-act { justify-self: start; min-height: var(--tap); padding-inline: 0; text-align: start; white-space: normal; }
.stand-words { display: flex; justify-content: space-between; gap: var(--s-3); align-items: center; min-height: var(--tap); margin-top: var(--s-3); color: var(--ink); text-decoration: none; }
.stand-def, .stand-week { margin-top: var(--s-2); max-width: var(--measure); }
/* the door to Progress: a 64 px row, its sparkline morphs into the Progress page's known line */
.stand-progress { display: grid; grid-template-columns: minmax(0, 1fr) auto 16px; align-items: center; gap: var(--s-3); min-height: 64px; margin-top: var(--s-3);
  border-block: 1px solid var(--hairline); color: var(--ink); text-decoration: none; }
.stand-progress .row-detail { color: var(--ink-3); }
.stand-progress > svg:last-child { color: var(--ink-3); }
.stand-spark { display: block; overflow: visible; }
.stand-spark-line { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.stand-spark-end { fill: var(--accent); stroke: var(--canvas); stroke-width: 1.5; }
.stand-none { margin-top: var(--s-4); color: var(--ink-2); }
.hero-def { margin-top: var(--s-1); color: var(--ink-2); }
.plan-note { margin-top: var(--s-3); max-width: var(--measure); }

/* ---------- Today in maintenance (round 4): the week strip, the kind of day, Where you stand by level ---------- */
.hero-week { margin-top: var(--s-5); }
.today-hero .wk-strip { margin-top: 0; }
.hero-weekline { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-3); }
.hero-weekline b { color: var(--ink); font-weight: 600; }
.hero-edit-week { display: inline-flex; align-items: center; min-height: var(--tap); margin-block: calc(-1 * var(--s-3)); color: var(--accent-ink); }
.hero-kind { margin-top: var(--s-3); color: var(--ink); }
.hero-kind.is-new, .hero-count.is-new { animation: vt-fade-in var(--dur-base) var(--ease-out) both; }
/* an Off day: the numeral's place says it (typography.h1), never a count of debt */
.hero-dayoff { font: 400 var(--fs-h1, 32px)/1.08 var(--font-display); letter-spacing: -0.02em; color: var(--ink); }
@media (min-width: 720px) { .hero-dayoff { font-size: 40px; } }
.hero-count.is-off { padding-block: var(--s-2) var(--s-1); }
/* "Welcome back": one sentence in the hero, under the kind of day */
.hero-welcome { margin-top: var(--s-2); max-width: var(--measure); color: var(--ink-2); font-size: 14px; line-height: 1.45; }
.plan-why { margin-top: var(--s-2); }
.plan-off { display: grid; gap: var(--s-3); justify-items: start; margin-top: var(--s-3); }
.plan-off p { margin: 0; color: var(--ink-2); max-width: var(--measure); }
.plan-later { margin-top: var(--s-5); }
.plan-later h3 { margin-bottom: var(--s-1); }
.plan-later .list { list-style: none; margin: 0; padding: 0; }
.plan-later-row { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: var(--s-2); align-items: baseline; padding: var(--s-2) 0; border-bottom: 1px solid var(--hairline); }
.plan-later-day { font-size: 13px; font-weight: 500; }
.plan-later .caption { color: var(--ink-2); }
.stand-figure { display: grid; gap: 2px; margin-top: var(--s-3); color: var(--ink); text-decoration: none; justify-self: start; }
.stand-figure .label { color: var(--ink-2); }
.stand-levels { list-style: none; margin: var(--s-4) 0 0; padding: 0; display: grid; gap: var(--s-1); }
.stand-level { display: grid; grid-template-columns: 28px minmax(0, 1fr) 104px; align-items: center; gap: var(--s-3); min-height: 28px; }
.stand-level-name { font-size: 13px; font-weight: 500; }
.stand-level .caption { text-align: end; color: var(--ink-2); }
.lv-track { background: var(--cell-empty); }
.lv-track .fill { background: var(--cell-known); }
.lv-gain { position: absolute; inset-block: 0; background: var(--accent); }
.stand-key { display: flex; align-items: center; gap: var(--s-2); margin-top: var(--s-2); }
.stand-key-swatch { width: 12px; height: 4px; border-radius: 2px; background: var(--accent); }
.stand-goal { margin-top: var(--s-5); padding: var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); display: grid; gap: var(--s-1); }
.stand-goal p { margin: 0; }
.stand-goal .caption { color: var(--ink-2); max-width: var(--measure); }
.stand-mocks { margin-top: var(--s-4); border-top: 1px solid var(--hairline); }
.stand-mocks-btn { display: flex; justify-content: space-between; align-items: center; width: 100%; min-height: var(--tap); padding: 0; border: 0; background: none; color: var(--ink); font: inherit; text-align: start; cursor: pointer; }
.stand-mocks-btn svg { transition: transform var(--dur-base) var(--ease-out); }
.stand-mocks-btn[aria-expanded="true"] svg { transform: rotate(90deg); }
@media (forced-colors: active) { .lv-gain, .stand-key-swatch { background: Highlight; forced-color-adjust: none; } }

/* ---------- Profile › Goals and week (round 4) ---------- */
.goals-page .page-head { padding-top: 0; }
.goal-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s-3); row-gap: 2px; padding: var(--s-4) 0; border-bottom: 1px solid var(--hairline); }
.goal-card > * { grid-column: 1 / -1; margin: 0; }
.goal-kind { grid-column: 1; font-size: 12px; color: var(--ink-3); }
.goal-what { grid-column: 1; font: 600 17px/1.3 var(--font-ui); letter-spacing: -0.01em; }
.goal-action { grid-column: 2; grid-row: 1 / 3; align-self: center; }
.goal-actions { display: flex; gap: var(--s-1); flex-wrap: wrap; justify-content: end; }
.goal-meta { font-size: 13px; color: var(--ink-2); max-width: var(--measure); }
.goal-meta:empty { display: none; }
.goal-track { margin-top: var(--s-2); height: 4px; background: var(--cell-empty); }
.goal-track .fill { background: var(--cell-known); }
.goal-gate { margin-top: var(--s-2); }
.goal-gate-list { list-style: none; margin: var(--s-1) 0 0; padding: 0; display: grid; gap: 2px; font-size: 13px; }
.goal-editor { margin-top: var(--s-3); display: grid; gap: var(--s-3); justify-items: start; }
.goal-editor .form-field, .goal-editor .date-row { width: 100%; }
.goal-add { margin-top: var(--s-4); }
.goal-sheet { margin-top: var(--s-4); padding: var(--s-4); border-radius: var(--r-card); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); display: grid; gap: var(--s-3); }
.goal-sheet-title { margin: 0; font: 600 17px/1.3 var(--font-ui); }
.goal-effects { list-style: none; margin: 0; padding: 0; font-size: 13px; color: var(--ink-2); }
.goal-effects li { padding: var(--s-2) 0; border-top: 1px solid var(--hairline); }
.week-sum { margin-top: var(--s-2); }
/* the week editor (features/profile/week-editor.js): the strip, then seven rows (a sheet per day) on a phone, or the
   strip's columns as tabs with the day's editor under them from 720 px */
.week-ed-strip { margin-top: var(--s-4); }
.week-ed .wk-strip { gap: 6px; }
.week-rows { margin-top: var(--s-4); border-top: 1px solid var(--hairline); }
.week-row { display: grid; grid-template-columns: minmax(0, 1fr) auto 16px; align-items: center; gap: var(--s-3); width: 100%; min-height: 56px; padding: 0;
  border: 0; border-bottom: 1px solid var(--hairline); background: none; color: var(--ink); font: inherit; text-align: start; cursor: pointer; }
.week-row-day { font: 500 15px/1.3 var(--font-ui); }
.week-row-val { font-size: 14px; color: var(--ink-2); text-align: end; }
.week-row svg { color: var(--ink-3); }
.week-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-tile); }
.week-chips { flex-wrap: wrap; }
.chip .week-later { color: var(--ink-3); }
.chip[aria-pressed="true"] .week-later { color: inherit; opacity: 0.8; }
.chip.is-later:not([aria-pressed="true"]) { border-style: dashed; }
.week-kind-line { margin: 0; color: var(--ink-2); }
.week-sheet-body { display: grid; gap: var(--s-2); }
.week-sheet-body .field-label { margin: var(--s-2) 0 0; }
.week-steps { display: flex; justify-content: space-between; gap: var(--s-3); padding-top: var(--s-2); border-top: 1px solid var(--hairline); }
.week-step { padding-inline: var(--s-2); color: var(--ink-2); }
.week-panel { display: grid; gap: var(--s-2); margin-top: var(--s-4); padding: var(--s-4); border-radius: var(--r-ctl); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); }
.week-panel .field-label { margin: var(--s-1) 0 0; }
.week-panel-title { margin: 0; font: 600 17px/1.3 var(--font-ui); }
@media (min-width: 720px) {
  .week-ed .wk-strip { gap: 10px; }
  .week-ed .wk-strip .runway-day { padding: var(--s-2) 0 6px; border-radius: var(--r-ctl); cursor: pointer; }
  .week-ed .wk-strip .runway-day:hover { background: color-mix(in oklab, var(--ink) 4%, transparent); }
  .week-ed .wk-strip .runway-day.is-sel { box-shadow: inset 0 0 0 1.5px var(--ink); }
  .week-ed .wk-strip .runway-day:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .week-ed .wk-strip .runway-day small { min-height: 12px; font-size: 11px; color: var(--ink-2); }
}
/* the B2 gate: a row per strand, the name and its state, a 4 px meter of the way to the gate */
.goal-gate-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; max-width: 520px; padding: var(--s-1) 0; }
.goal-gate-name { font: 500 14px/1.35 var(--font-ui); color: var(--ink); }
.goal-gate-state { font-size: 13px; color: var(--ink-2); }
.goal-gate-track { height: 4px; margin-top: 4px; background: var(--cell-empty); }
.goal-gate-track .fill { background: var(--cell-known); }
@media (min-width: 720px) {
  .goal-gate-row { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s-4); }
  .goal-gate-track { grid-column: 1 / -1; }
  .goal-gate-state { text-align: end; }
}
.week-away { padding: 10px 12px; border-radius: var(--r-tile); background: var(--surface-2); font-size: 13px; color: var(--ink-2); max-width: var(--measure); }

/* ---------- keyboard mode (core/keyboard.js, round 6) ----------
   body.kb is on while a text field has the focus and the on-screen keyboard is up. The chrome gives way: no app bar,
   tab bar, docks or hints, no safe-area padding at the bottom (there is no home indicator under the content while the
   keyboard is up). Every typing screen ends in one row on the keyboard: the field, then at most three 44 px buttons
   with the primary at the end. A .kb-fit box is sized to the visual viewport (--vv-h) and follows its pan (--vv-top). */
:root .kb-fit { height: var(--vv-h, 100dvh); transform: translateY(var(--vv-top, 0px)); }
body.kb .bar, body.kb #tabs-slot, body.kb #banner, body.kb .dock, body.kb .rd-dock, body.kb .pr-queue-btn, body.kb .sc-mark-dock,
body.kb .kb-hide, body.kb .field-hint, body.kb .rs-tip { display: none; }
body.kb .toast { bottom: calc(var(--kb, 0px) + var(--s-3)); }
/* a long prompt keeps to three lines (two for a mistake card's task and context); a tap shows all of it */
body.kb .kb-clamp:not(.is-full) { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--kb-lines, 3); line-clamp: var(--kb-lines, 3); overflow: hidden; cursor: pointer; }
/* a sticky header on a form page stays on screen while iOS pans the page to the caret */
body.kb .kb-stick { position: fixed; inset-inline: 0; top: var(--vv-top, 0px); z-index: var(--z-bar); }
/* a form's action row on the keyboard: fixed to the bottom of the visual viewport */
body.kb .kb-dock { position: fixed; inset-inline: 0; bottom: var(--kb, 0px); z-index: var(--z-bar);
  display: flex; align-items: center; gap: var(--s-2); margin: 0; padding: 6px max(var(--gutter), env(safe-area-inset-left)); background: var(--canvas); border-top: 1px solid var(--hairline); }
body.kb .kb-dock .btn { min-height: var(--tap); }
body.kb .kb-dock .btn-primary { flex: 1; max-width: none; }
/* a button with a shorter label for the keyboard row */
.kb-short { display: none; }
body.kb .kb-long { display: none; }
body.kb .kb-short { display: inline; }
/* only with the keyboard up (a form's slim row on the keyboard) */
.kb-only { display: none; }
/* a page (not a fitted round) gets room at its end, so a field low on it scrolls above the keyboard instead of iOS
   panning the whole page (the jump of 200 to 450 px in the audit) */
body.kb main.page { padding-bottom: calc(var(--kb-screen, 0px) + var(--s-4)); }
/* bottom sheets with a field (the reader's word sheet, the script's marked words): on the keyboard, no taller than the
   visible screen, their buttons in reach. ui/sheet.js sheets (the round size picker) do this themselves (ui.css). */
body.kb .tv-sheet, body.kb .sc-sheet { bottom: var(--kb, 0px); max-height: var(--vv-h, 100dvh); }
body.kb .tv-sheet, body.kb .sc-sheet { padding-bottom: var(--s-3); }

/* keyboard mode, a short prompt (core/keyboard.js fitPrompt, round 6 follow-up): while the band between the header and
   the field is empty (nothing open on the card but a plain "Right"), it is the prompt's. A short prompt grows toward the
   normal prompt size with the visible height (30 px from 400 px up, never under 22) and sits in the middle of the space
   above the field. Once feedback opens, the card is as before (22 px at the top), so the answer and the sentence to
   type keep their room. The field and its row stay where they are on every card (the field keeps the bottom of the
   column); a long prompt keeps 22 px and three lines. Nothing animates: the size follows the variables, and a card
   change is the card's own transition. */
body.kb .pr-card:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok), .pr-typecheck)) .prompt.kb-prompt-short,
body.kb .wb-rcard:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) .prompt.kb-prompt-short,
body.kb .qs-round.is-produce .qs-stage:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) .qs-prompt.kb-prompt-short {
  font-size: clamp(22px, calc(var(--vv-h, 100dvh) * 0.075), var(--fs-prompt)); line-height: 1.18; letter-spacing: -0.012em; }
/* the typed rounds (round, reading, script words): the prompt box takes the band and centres what it holds */
body.kb .pr-card:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok), .pr-typecheck)) > .pr-promptbox:has(> .prompt.kb-prompt-short) { flex: 1 0 auto; display: flex; flex-direction: column; justify-content: center; padding-bottom: var(--s-4); }
/* the spot check (task, prompt and field are the card's own children): auto margins centre the task and the prompt */
body.kb .pr-card:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))):has(> .prompt.kb-prompt-short) > .pr-task { margin-top: auto; }
body.kb .pr-card:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) > .prompt.kb-prompt-short { margin-bottom: auto; padding-bottom: var(--s-4); }
body.kb .pr-card:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))):has(> .prompt.kb-prompt-short) > .answer { margin-top: 0; }
/* Quick sort: the word's line, the task and the prompt in the middle of the band */
body.kb .qs-round.is-produce .qs-stage:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))):has(.qs-prompt.kb-prompt-short) .qs-level { margin-top: auto; }
body.kb .qs-round.is-produce .qs-stage:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) .qs-prompt.kb-prompt-short { margin-bottom: auto; padding-bottom: var(--s-4); }
body.kb .qs-round.is-produce .qs-stage:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))):has(.qs-prompt.kb-prompt-short) .qs-answer { margin-top: 0; }
/* Word building: the card's meta stays at the top, the prompt and its hint take the middle of the band */
body.kb .wb-rscroll > .wb-rcard:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) > .wb-cbody:has(> .prompt.kb-prompt-short) { flex: 1 0 auto; display: flex; flex-direction: column; padding-bottom: var(--s-4); }
body.kb .wb-rcard:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) .wb-cbody > .prompt.kb-prompt-short { margin-top: auto; }
body.kb .wb-rcard:not(:has(.reveal-answer.is-open :is(.pr-fb, .wb-fb) > :not(.pr-res.is-ok, .wb-res.is-ok))) .wb-cbody:has(> .prompt.kb-prompt-short) > :last-child { margin-bottom: auto; }
