/* ==========================================================================
   Terapi Afasia - Base
   Reset, document defaults, layout primitives, accessibility floor.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body, h1, h2, h3, h4, p, figure, ul, ol, dl, dd {
  margin: 0;
  padding: 0;
}

ul[class], ol[class] { list-style: none; }

img, svg, video, canvas {
  display: block;
  max-width: 100%;
}

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

body {
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: var(--lh-normal);
  color: var(--c-ink);
  background: var(--c-bg);

  /* No text selection anywhere in the therapy flow. A long-press that
     selects a word is a gesture the patient did not intend and cannot
     undo. Re-enabled explicitly on inputs below. */
  -webkit-user-select: none;
  user-select: none;

  /* Kill the 300ms tap delay and double-tap zoom on every surface. */
  touch-action: manipulation;

  /* Never bounce or pull-to-refresh mid-session. */
  overscroll-behavior: none;

  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}

input, textarea {
  -webkit-user-select: text;
  user-select: text;
}

/* --- Focus -----------------------------------------------------------------
   Focus rings are never removed. A caregiver may pair a keyboard, and the
   patient may use a switch device later. */

:focus-visible {
  outline: 3px solid var(--c-focus);
  outline-offset: 3px;
  border-radius: var(--r-2);
}

/* --- Motion ----------------------------------------------------------------
   Honour the OS setting. The syllable highlight stays, because it carries
   timing information rather than decoration, but it stops sliding. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- App frame -------------------------------------------------------------
   dvh with a vh fallback. Mobile Safari resizes the toolbar and 100vh
   overflows; dvh tracks the real viewport. */

.app {
  /* --chrome-offset is 0 in the real app. The M1 preview page sets it so
     its debug strip does not distort the layout being measured. */
  height: calc(100vh  - var(--chrome-offset, 0px));
  height: calc(100dvh - var(--chrome-offset, 0px));
  display: flex;
  flex-direction: column;
  overflow: hidden;      /* the session screen never scrolls */
  padding:
    env(safe-area-inset-top)
    env(safe-area-inset-right)
    env(safe-area-inset-bottom)
    env(safe-area-inset-left);
}

/* Scrollable variant, for the dashboard and long settings pages only.
   Never for a practice screen. */
.app--scroll          { height: auto; min-height: 100dvh; overflow: visible; }
.app--scroll .app__body { justify-content: flex-start; }

.app__body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--body-pad) var(--s-5);
  min-height: 0;

  /* Design floor is a 768px-tall tablet, where nothing scrolls. Below that
     the practice area scrolls INSIDE this element while the top bar and the
     control bar stay pinned. Without this the app frame's overflow:hidden
     silently clips the phrase instead of fitting it, which is worse than a
     scrollbar. The rating bar must always be reachable. */
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.wrap {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
}

.wrap--wide { max-width: var(--measure-wide); }

/* --- Stacks ---------------------------------------------------------------- */

.stack     > * + * { margin-top: var(--s-4); }
.stack-2   > * + * { margin-top: var(--s-2); }
.stack-5   > * + * { margin-top: var(--s-5); }
.stack-6   > * + * { margin-top: var(--s-6); }
.stack-7   > * + * { margin-top: var(--s-7); }

.row {
  display: flex;
  align-items: center;
  gap: var(--tap-gap);
}

.row--tight  { gap: var(--s-3); }
.row--center { justify-content: center; }
.row--between{ justify-content: space-between; }
.row--wrap   { flex-wrap: wrap; }

.center-text { text-align: center; }

/* --- Type ------------------------------------------------------------------
   One idea per line, left aligned, never justified. Justified text creates
   uneven word spacing which measurably slows impaired reading. */

h1, h2, h3 {
  line-height: var(--lh-tight);
  font-weight: var(--fw-bold);
  text-wrap: balance;
}

h1 { font-size: var(--t-title); }
h2 { font-size: var(--t-instruction); }
h3 { font-size: var(--t-body); }

p { max-width: 60ch; }

.t-instruction {
  font-size: var(--t-instruction);
  font-weight: var(--fw-medium);
  line-height: var(--lh-normal);
}

.t-label {
  font-size: var(--t-label);
  font-weight: var(--fw-medium);
  color: var(--c-ink-2);
}

.t-caption {
  font-size: var(--t-caption);
  color: var(--c-ink-2);
}

.t-muted { color: var(--c-ink-2); }

.t-num {
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-bold);
}

/* --- Utility ---------------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.hidden { display: none !important; }

hr.rule {
  border: 0;
  border-top: 1px solid var(--c-line);
  margin-block: var(--s-6);
}
