/* Layout and components.
 *
 * RTL policy: no `left`, `right`, `margin-left`, `padding-right` or
 * `text-align: left|right` appears anywhere below. Everything uses logical
 * properties (inline-start/end), so setting dir="rtl" on <html> mirrors the
 * entire interface with no per-rule overrides.
 *
 * Responsive policy: mobile-first. A bottom tab bar becomes a side rail at
 * 720px, and the grid widens again for TV-class viewports at 1800px.
 */

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

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

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: 1.55;
  min-block-size: 100dvh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

button {
  background: none;
  border: none;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

h1, h2, h3, h4 {
  line-height: 1.15;
  font-weight: 640;
  letter-spacing: -0.02em;
}

.num {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ------------------------------------------------------------- app shell */

.app {
  display: grid;
  /* An explicit minmax(0, 1fr) column. Without it the grid creates an implicit
     `auto` column that sizes to its widest child, so a wide nav or a long
     unbreakable string widens the whole page instead of being constrained by
     it. This is the fix for horizontal scroll on narrow screens. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: 1fr auto;
  min-block-size: 100dvh;
}

.main {
  padding-inline: var(--sp-4);
  padding-block: var(--sp-5) calc(var(--sp-7) + 4rem);
  max-inline-size: 1180px;
  margin-inline: auto;
  inline-size: 100%;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Buttons carry white-space: nowrap, so on a narrow phone an action label
     cannot shrink to fit beside a heading — it has to be allowed to wrap onto
     its own line instead of pushing the page sideways. */
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-block-end: var(--sp-5);
}

.topbar__title {
  font-size: var(--text-2xl);
}

.topbar__sub {
  color: var(--text-dim);
  font-size: var(--text-sm);
}

.topbar__actions {
  display: flex;
  /* Buttons are nowrap by nature, so a header with two long labels — "Which
     hats do you wear?" beside "Add a hat" — cannot fit a 320px phone unless
     the row itself is allowed to break. */
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
}

/* ------------------------------------------------------------ navigation */

.nav {
  position: sticky;
  inset-block-end: 0;
  z-index: 20;
  display: grid;
  grid-auto-flow: column;
  /* minmax(0, 1fr), not 1fr: a bare `1fr` floors at min-content, so once the
     bar carries six destinations the items refuse to shrink and push the whole
     page into horizontal scroll on a narrow phone. */
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--sp-1);
  background: var(--bg-elevated);
  border-block-start: 1px solid var(--line);
  padding: var(--sp-2) var(--sp-2) max(var(--sp-2), env(safe-area-inset-bottom));

  /* The nav is itself a grid item of .app, where the default `min-width: auto`
     lets its content dictate its width. Pinning the box to the grid area means
     six destinations can never widen the page — the tracks distribute inside a
     fixed box instead of the box growing to fit the tracks. */
  inline-size: 100%;
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow: hidden;
}

.nav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding-block: var(--sp-2);
  border-radius: var(--radius-sm);
  color: var(--text-faint);
  font-size: var(--text-xs);
  font-weight: 560;
  min-inline-size: 0;
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

/* Labels truncate rather than widening the bar. */
.nav__item > span {
  max-inline-size: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nav__item:hover {
  color: var(--text-dim);
  background: var(--surface-hover);
}

.nav__item[aria-current="page"] {
  color: var(--accent-text);
  background: var(--accent-soft);
}

/* ---------------------------------------------------------------- pieces */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-5);
}

.card--flush {
  padding: 0;
  overflow: hidden;
}

.bento {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}

.bento__wide {
  grid-column: 1 / -1;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

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

.row--between {
  justify-content: space-between;
}

.wrap {
  flex-wrap: wrap;
}

.muted {
  color: var(--text-dim);
}

.faint {
  color: var(--text-faint);
  font-size: var(--text-sm);
}

.eyebrow {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 640;
  color: var(--text-faint);
}

.divider {
  block-size: 1px;
  background: var(--line);
  border: 0;
  margin-block: var(--sp-4);
}

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.65rem 1.05rem;
  border-radius: var(--radius-full);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text);
  font-weight: 580;
  font-size: var(--text-sm);
  white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease-spring),
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.btn:hover {
  background: var(--surface-hover);
}

.btn:active {
  transform: scale(0.96);
}

.btn--primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: transparent;
  font-weight: 660;
}

.btn--primary:hover {
  background: var(--accent);
  filter: brightness(1.06);
}

.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-dim);
}

.btn--ghost:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.btn--danger {
  color: var(--danger);
  border-color: transparent;
  background: var(--danger-soft);
}

.btn--block {
  inline-size: 100%;
}

.btn--icon {
  padding: 0.55rem;
  border-radius: var(--radius-full);
}

.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ----------------------------------------------------------------- forms */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.field__label {
  font-size: var(--text-sm);
  font-weight: 580;
  color: var(--text-dim);
}

.field__help {
  font-size: var(--text-xs);
  color: var(--text-faint);
  line-height: 1.5;
}

.input,
.select,
.textarea {
  inline-size: 100%;
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.7rem 0.85rem;
  color: var(--text);
  transition: border-color var(--dur-fast) var(--ease-out);
  text-align: start;
  /* A text input carries an intrinsic width (the `size` attribute, ~20
     characters). As a flex item that intrinsic width becomes its shrink floor,
     so without this an input inside a .row refuses to narrow and pushes the
     page sideways. */
  min-inline-size: 0;
}

.input:focus,
.select:focus,
.textarea:focus {
  border-color: var(--accent-text);
  outline: none;
}

.input::placeholder,
.textarea::placeholder {
  color: var(--text-faint);
}

.textarea {
  min-block-size: 5.5rem;
  resize: vertical;
  line-height: 1.6;
}

.grid-2 {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: 1fr;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.chip {
  padding: 0.35rem 0.75rem;
  border-radius: var(--radius-full);
  border: 1px solid var(--line-strong);
  font-size: var(--text-sm);
  font-weight: 560;
  color: var(--text-dim);
  transition: all var(--dur-fast) var(--ease-out);
}

.chip[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: transparent;
}

/* ------------------------------------------------------------ onboarding */

.onboard {
  max-inline-size: 34rem;
  margin-inline: auto;
  padding-block: var(--sp-7);
  text-align: start;
}

.onboard h1 {
  font-size: var(--text-3xl);
  margin-block-end: var(--sp-3);
}

.onboard__body {
  color: var(--text-dim);
  margin-block-end: var(--sp-5);
}

.onboard__line {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  flex-wrap: wrap;
  border-block-end: 2px solid var(--accent);
  padding-block-end: var(--sp-2);
  margin-block-end: var(--sp-4);
}

.onboard__prefix {
  color: var(--text-dim);
  font-size: var(--text-lg);
  white-space: nowrap;
}

.onboard__input {
  flex: 1 1 12rem;
  min-inline-size: 0; /* see the note on .input — same intrinsic-width trap */
  inline-size: 100%;
  background: none;
  border: none;
  font-size: var(--text-lg);
  font-weight: 620;
  color: var(--text);
  padding-block: var(--sp-1);
}

.onboard__input:focus {
  outline: none;
}

/* ----------------------------------------------------------------- timer */

.timer {
  display: grid;
  place-items: center;
  gap: var(--sp-4);
  text-align: center;
  padding-block: var(--sp-5);
}

.timer__clock {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-hero);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.04em;
  /* Latin digits read left-to-right even inside an RTL document. */
  direction: ltr;
  unicode-bidi: isolate;
}

.timer__clock--running {
  color: var(--accent-text);
}

.timer__label {
  color: var(--text-dim);
  font-size: var(--text-sm);
}

.timer__track {
  inline-size: min(100%, 26rem);
  block-size: 6px;
  border-radius: var(--radius-full);
  background: var(--line);
  overflow: hidden;
}

.timer__fill {
  block-size: 100%;
  background: var(--accent);
  border-radius: inherit;
  transition: inline-size var(--dur) linear;
}

.timer__modes {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  justify-content: center;
}

/* ------------------------------------------------------------ habit rows */

.habit {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-spring);
}

.habit:hover {
  border-color: var(--line-strong);
}

.habit--done {
  border-color: transparent;
  background: var(--accent-soft);
}

.habit--risk {
  border-color: var(--warn);
}

.habit__body {
  flex: 1;
  min-inline-size: 0;
}

.habit__name {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.habit--done .habit__name {
  text-decoration: line-through;
  text-decoration-thickness: 2px;
  color: var(--text-dim);
}

.habit__cue {
  font-size: var(--text-sm);
  color: var(--text-faint);
  margin-block-start: 2px;
}

.habit__actions {
  display: flex;
  gap: var(--sp-2);
  flex-shrink: 0;
}

.habit__depth {
  padding-inline-start: calc(var(--depth, 0) * var(--sp-5));
}

.tick {
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border-radius: var(--radius-full);
  border: 2px solid var(--line-strong);
  display: grid;
  place-items: center;
  color: transparent;
  flex-shrink: 0;
  transition: all var(--dur) var(--ease-spring);
}

.tick:hover {
  border-color: var(--accent-text);
  color: var(--text-faint);
}

.tick--on {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-ink);
}

/* --------------------------------------------------------------- badges */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 620;
  background: var(--surface-hover);
  color: var(--text-dim);
}

.badge--accent {
  background: var(--accent-soft);
  color: var(--accent-text);
}

.badge--warn {
  background: var(--warn-soft);
  color: var(--warn);
}

.badge--danger {
  background: var(--danger-soft);
  color: var(--danger);
}

.notice {
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--warn);
  background: var(--warn-soft);
  border-radius: var(--radius-sm);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--text-sm);
  color: var(--text);
}

.notice--calm {
  border-inline-start-color: var(--calm);
  background: color-mix(in srgb, var(--calm) 10%, transparent);
}

/* ----------------------------------------------------------------- stats */

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-3);
}

.stat {
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-4);
}

.stat__value {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-2xl);
  font-weight: 620;
  line-height: 1.1;
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
}

.stat__label {
  font-size: var(--text-xs);
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-block-start: var(--sp-1);
}

.hero-number {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums;
  font-size: clamp(3rem, 12vw, 5rem);
  font-weight: 640;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--accent-text);
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
}

/* ----------------------------------------------------------------- chart */

.chart {
  inline-size: 100%;
  block-size: auto;
  display: block;
  overflow: visible;
}

/* The chart is a value plot, not a layout: it stays LTR in both directions so
   time always reads earliest-to-latest along the same axis. */
.chart-wrap {
  direction: ltr;
  margin-block: var(--sp-4);
}

/* ---------------------------------------------------------------- ledger */

.ledger {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.ledger__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  font-size: var(--text-sm);
}

.ledger__when {
  color: var(--text-faint);
  font-size: var(--text-xs);
  white-space: nowrap;
}

/* ----------------------------------------------------------------- modal */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.62);
  display: grid;
  place-items: end center;
  z-index: 50;
  animation: fade var(--dur) var(--ease-out);
}

.modal {
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-start-start-radius: var(--radius-lg);
  border-start-end-radius: var(--radius-lg);
  inline-size: min(100%, 34rem);
  max-block-size: 92dvh;
  overflow-y: auto;
  padding: var(--sp-5);
  padding-block-end: max(var(--sp-5), env(safe-area-inset-bottom));
  animation: rise var(--dur-slow) var(--ease-spring);
}

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-block-end: var(--sp-4);
}

@keyframes fade {
  from { opacity: 0; }
}

@keyframes rise {
  from { transform: translateY(16px); opacity: 0; }
}

/* ----------------------------------------------------------------- toast */

.toasts {
  position: fixed;
  inset-block-end: 5.5rem;
  inset-inline: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  pointer-events: none;
  z-index: 60;
  padding-inline: var(--sp-4);
}

.toast {
  background: var(--accent);
  color: var(--accent-ink);
  padding: 0.6rem 1.1rem;
  border-radius: var(--radius-full);
  font-weight: 620;
  font-size: var(--text-sm);
  box-shadow: var(--shadow-lift);
  animation: rise var(--dur) var(--ease-spring);
  max-inline-size: 100%;
}

.toast--plain {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line-strong);
}

.empty {
  text-align: center;
  color: var(--text-faint);
  padding-block: var(--sp-7);
  font-size: var(--text-sm);
}

/* ----------------------------------------------------------- breakpoints */

@media (min-width: 560px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
  .stats { grid-template-columns: repeat(4, 1fr); }
  .modal-backdrop { place-items: center; }
  .modal {
    border-radius: var(--radius-lg);
    inline-size: min(100% - 2rem, 34rem);
  }
}

/* Tablet and up: bottom bar becomes a side rail. */
@media (min-width: 720px) {
  .app {
    grid-template-rows: 1fr;
    grid-template-columns: var(--rail) minmax(0, 1fr);
  }

  .main {
    grid-column: 2;
    min-inline-size: 0;
    padding-inline: var(--sp-6);
    padding-block-end: var(--sp-7);
  }

  .nav {
    grid-column: 1;
    grid-row: 1;
    position: sticky;
    inset-block-start: 0;
    block-size: 100dvh;
    grid-auto-flow: row;
    grid-auto-rows: max-content;
    align-content: start;
    gap: var(--sp-1);
    padding: var(--sp-5) var(--sp-3);
    border-block-start: none;
    border-inline-end: 1px solid var(--line);
    background: var(--bg);
  }

  .nav__brand {
    padding-inline: var(--sp-3);
    margin-block-end: var(--sp-5);
    font-weight: 700;
    font-size: var(--text-lg);
    letter-spacing: -0.02em;
  }

  .nav__item {
    flex-direction: row;
    justify-content: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-3);
    font-size: var(--text-sm);
  }

  .bento { grid-template-columns: repeat(2, 1fr); }
  .toasts { inset-block-end: var(--sp-6); }
}

@media (min-width: 1080px) {
  .bento { grid-template-columns: repeat(3, 1fr); }
}

/* TV-class displays: viewed from across a room, so everything scales up and
   focus rings get much louder for remote-control navigation. */
@media (min-width: 1800px) {
  :root {
    --text-base: 1.25rem;
    --text-sm: 1.05rem;
    --text-xs: 0.95rem;
    --text-2xl: 2.4rem;
    --rail: 320px;
  }

  .main { max-inline-size: 1600px; }

  :focus-visible {
    outline-width: 4px;
    outline-offset: 4px;
  }
}

.nav__brand { display: none; }

@media (min-width: 720px) {
  .nav__brand { display: block; }
}

/* ================================================================ consultant
   The advice surface. Three things share it — the counsel cards, the kill
   switch and the panic switch — and their visual weight is deliberately
   unequal: advice reads as content, the kill switch as an invitation, the
   panic switch as a quiet exit that only raises its voice when warranted. */

.counsel { border-inline-start: 3px solid var(--accent); }

.counsel__source {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--text-xs); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-faint); margin-block-end: var(--sp-2);
}

.tag {
  font-size: var(--text-xs); padding: 1px 6px; border-radius: var(--radius-full);
  border: 1px solid var(--line-strong); color: var(--text-faint);
  text-transform: none; letter-spacing: 0;
}

/* The evidence line, tinted. This is the part that proves the advice was read
   off this user's data rather than pulled from a rotation of platitudes, so it
   gets the accent colour that nothing else in the card is allowed. */
.counsel__because {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  color: var(--accent); font-size: var(--text-sm); margin-block: var(--sp-2);
}
.counsel__because svg { flex: none; margin-block-start: 3px; }

.counsel__actions { justify-content: space-between; align-items: center; gap: var(--sp-3); }
.counsel__act { font-weight: 600; }

/* -------------------------------------------------------------- the switches */

.switch {
  display: flex; align-items: center; gap: var(--sp-4);
  inline-size: 100%; text-align: start; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line);
  transition: border-color var(--dur) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.switch:hover { border-color: var(--line-strong); background: var(--surface-hover); }
.switch:active { transform: scale(0.995); }
.switch__icon { flex: none; color: var(--accent); }
.switch__body { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.switch__body strong { font-size: var(--text-lg); }
.switch__count {
  margin-inline-start: auto; font-family: var(--font-numeric);
  font-size: var(--text-2xl); color: var(--text-faint);
  direction: ltr; unicode-bidi: isolate;
}

/* The panic switch stays grey until the reading is actually bad. A permanently
   red button would make this screen stressful to open, which is the opposite of
   what someone reaching for it needs. */
.switch--panic .switch__icon { color: var(--text-faint); }
.switch--panic.switch--hot { border-color: var(--warn); }
.switch--panic.switch--hot .switch__icon { color: var(--warn); }

@media (prefers-reduced-motion: reduce) {
  .switch { transition: none; }
  .switch:active { transform: none; }
}

/* =============================================================== kill switch
   Full-screen by necessity, not for drama. Someone opens this because their
   head is loud; a nav bar and three streak counters would add to the noise
   they came to dump. */

.dump {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: var(--bg); padding: var(--sp-5); overflow-y: auto;
}
body.is-dumping { overflow: hidden; }

.dump__capture, .dump__triage, .dump__done {
  inline-size: min(34rem, 100%);
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-4);
  text-align: center;
}

.dump__exit {
  position: fixed; inset-block-start: var(--sp-4); inset-inline-end: var(--sp-4);
  background: none; border: 0; color: var(--text-faint); cursor: pointer;
}

.dump__prompt { font-size: var(--text-lg); color: var(--text-dim); }

/* The count is the only feedback capture gives — no list, by design. It is
   this large because watching it climb is the whole reward for emptying, and
   nothing else on the screen is allowed to move. */
.dump__meter { display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); }
.dump__count {
  font-size: clamp(3.5rem, 18vw, 5.5rem); font-weight: 700; line-height: 1;
  color: var(--accent); font-family: var(--font-numeric);
  direction: ltr; unicode-bidi: isolate;
}
.dump__caught { color: var(--text-faint); font-size: var(--text-sm); }

/* A three-minute bar. Nothing happens when it fills: a timebox you cannot
   fail, only notice — enough to end a spiral, not enough to add pressure. */
.dump__box {
  inline-size: 8rem; block-size: 2px; background: var(--line);
  margin-block-start: var(--sp-3); border-radius: var(--radius-full); overflow: hidden;
}
.dump__boxFill { block-size: 100%; background: var(--line-strong); transition: inline-size 1s linear; }

.dump__field {
  inline-size: 100%; min-inline-size: 0;
  font-size: var(--text-xl); padding: var(--sp-4);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  text-align: center;
}
.dump__field:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.dump__hint { color: var(--text-faint); font-size: var(--text-xs); }

.dump__loop {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4); border-radius: var(--radius-full);
  background: var(--warn-soft); color: var(--warn); font-size: var(--text-sm);
  animation: dumpLoop 2.2s var(--ease-out) forwards;
}
@keyframes dumpLoop {
  0% { opacity: 0; transform: translateY(4px); }
  12%, 80% { opacity: 1; transform: none; }
  100% { opacity: 0; }
}

.dump__done { margin-block: auto; color: var(--accent); }
.dump__done h2, .dump__done p { color: var(--text); }

/* ---------------------------------------------------------------- triage */

.dump__step { color: var(--text-faint); font-size: var(--text-sm); }

.dump__thought {
  font-size: var(--text-xl); line-height: 1.5; margin: 0;
  padding: var(--sp-5); border-radius: var(--radius);
  background: var(--surface); border-inline-start: 3px solid var(--accent);
  text-align: start; inline-size: 100%;
}
.dump__times {
  display: block; margin-block-start: var(--sp-2);
  font-size: var(--text-xs); color: var(--warn);
}
.dump__diagnosis { color: var(--warn); font-size: var(--text-base); }
.dump__question { font-weight: 600; }

.dump__doors {
  display: grid; gap: var(--sp-2); inline-size: 100%;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}
.dump__door {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: var(--sp-4) var(--sp-3); cursor: pointer;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.dump__door:hover { border-color: var(--accent); background: var(--surface-hover); }
.dump__door span { font-size: var(--text-xs); }
.dump__door--drop { color: var(--text-faint); }

/* ============================================================= panic wizard */

.rescue {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  padding: var(--sp-4); overflow-y: auto;
}
body.is-rescuing { overflow: hidden; }

.rescue__sheet {
  inline-size: min(32rem, 100%);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: var(--sp-5);
}

.rescue__facts { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-2); }
.rescue__facts li { display: flex; align-items: center; gap: var(--sp-3); }
.rescue__facts svg { flex: none; color: var(--warn); }

.rescue__move {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-4); cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius);
}
.rescue__move.is-on { border-color: var(--accent); }
.rescue__moveBody { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.rescue__moveBody span { font-size: var(--text-sm); }

/* "Parked, not deleted" sits on the control itself, never in a help page. It
   is the sentence that makes the tick acceptable to someone who is panicking. */
.rescue__safe { margin-block-start: var(--sp-2); font-size: var(--text-xs); color: var(--calm); }

.rescue__one { border: 1px solid var(--accent); text-align: center; }

/* ------------------------------------------------------------ hat swatches */

.swatches { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* Each swatch sets its own data-hat, so --accent inside it IS the colour it
   offers. No per-colour CSS class and no inline styles — adding a ninth hue
   means one entry in the ramp and nothing here changes. */
.swatch {
  inline-size: 2rem; block-size: 2rem; padding: 0;
  border-radius: var(--radius-full); cursor: pointer;
  background: var(--accent);
  border: 2px solid transparent;
  transition: transform var(--dur-fast) var(--ease-out);
}
.swatch:hover { transform: scale(1.12); }

/* The selected ring sits outside the fill so it reads against both a light and
   a dark page, which a simple border on the fill itself would not. */
.swatch[aria-checked="true"] {
  border-color: var(--bg);
  box-shadow: 0 0 0 2px var(--accent);
}
.swatch:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .swatch { transition: none; }
  .swatch:hover { transform: none; }
}

/* A tinted row shows its colour as an edge rather than a wash: at full
   saturation behind text it would fight the copy for attention. */
.habit[data-hat] { border-inline-start: 3px solid var(--accent); }

/* An unselected chip states its colour quietly; the selected one commits. */
.chip[data-hat] { border-color: var(--accent-soft); }
.chip[data-hat][aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* ==================================================================== study
   The verdict card is the screen's whole reason to exist, so it is the only
   thing here allowed a coloured edge — everything else stays neutral so the
   one number that matters is never competing for attention. */

.verdict { border-inline-start: 3px solid var(--line-strong); }
.verdict--ok    { border-inline-start-color: var(--calm); }
.verdict--tight { border-inline-start-color: var(--warn); }
.verdict--no    { border-inline-start-color: var(--danger); }

.verdict__head { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--text-lg); }
.verdict--ok .verdict__head svg    { color: var(--calm); }
.verdict--tight .verdict__head svg { color: var(--warn); }
.verdict--no .verdict__head svg    { color: var(--danger); }

.verdict__body { margin-block: var(--sp-3); }

.verdict__stats {
  display: grid; gap: var(--sp-3); margin: 0;
  grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
}
.verdict__stats dt { font-size: var(--text-xs); color: var(--text-faint); }
.verdict__stats dd { margin: 0; font-size: var(--text-xl); font-family: var(--font-numeric); }

/* Figures are isolated so an Arabic page does not reorder "12h of 40h". */
.num { direction: ltr; unicode-bidi: isolate; }

.meter {
  block-size: 4px; background: var(--line); border-radius: var(--radius-full);
  overflow: hidden; margin-block: var(--sp-2);
}
.meter__fill { block-size: 100%; background: var(--accent); }

.warnline { display: flex; align-items: center; gap: var(--sp-2); color: var(--warn); }
.warnline svg { flex: none; }

.nextup { border: 1px solid var(--accent); }

.section { font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-faint); margin-block-start: var(--sp-5); }

.empty { align-items: center; text-align: center; padding-block: var(--sp-7); gap: var(--sp-4); }
.empty svg { color: var(--accent); }

/* --------------------------------------------------------------- focus mode */

/* Silence needs to be visible, or it is not trusted. Someone who cannot tell
   that cues are muted will keep checking, which is the anxiety the mode set
   out to remove. */
.focusbar {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--radius);
  background: var(--accent-soft); color: var(--accent-text);
  font-size: var(--text-sm);
}
.focusbar svg { flex: none; }

.grid-2 { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); }

/* ============================================================== focus room */

/* No nav highlight, no streaks, no counts. Wide margins and one column: the
   room is defined by what is not in it. */
.focusroom { max-inline-size: 34rem; margin-inline: auto; }
.focusroom__label { display: flex; align-items: center; gap: var(--sp-2); color: var(--accent-text); }
.focusroom__clock { text-align: center; padding-block: var(--sp-6); }
.focusroom__time {
  font-size: clamp(3rem, 16vw, 5rem); font-weight: 700; line-height: 1;
  font-family: var(--font-numeric); margin-block: var(--sp-3);
}
.focusroom__note { font-size: var(--text-xs); }

.player .chips { margin-block: var(--sp-3); }
.range { inline-size: 100%; accent-color: var(--accent); }

/* ================================================================= decide */

/* The balance bar. Two blocks that always total 100%, because a single number
   out of context is unreadable and a count would reintroduce the bias the
   weighting exists to remove. */
.scale {
  display: flex; block-size: 10px; border-radius: var(--radius-full);
  overflow: hidden; background: var(--line);
}
.scale__a { background: var(--accent); }
.scale__b { background: var(--calm); }

.factor { gap: var(--sp-2); padding: var(--sp-3); }
.chip--tight { padding-inline: var(--sp-3); font-family: var(--font-numeric); }

/* =============================================================== progress */

.level { text-align: center; }
.level__name { font-size: var(--text-2xl); margin-block: var(--sp-2) var(--sp-4); }

.milestone { gap: var(--sp-3); align-items: center; }
.milestone svg { flex: none; color: var(--accent); }
.milestone--next { border: 1px dashed var(--line-strong); }
.milestone--next svg { color: var(--text-faint); }

/* ==================================================================== pact */

/* The goal sits above both sides' numbers because it is what they are evidence
   FOR. Counts first and this is a chore chart with a mission statement on it. */
.goalcard { border-inline-start: 3px solid var(--accent); }
.goalcard__goal { font-size: var(--text-xl); margin-block: var(--sp-2); }

/* Equal weight, always. The parent's card is drawn first in the DOM; if the
   child's led, every other choice here would be decoration on a monitor. */
.sidecard { display: flex; flex-direction: column; gap: var(--sp-2); }
.sidecard--met { border-color: var(--accent); }
.sidecard .btn { margin-block-start: auto; }

/* ------------------------------------------------------- the ten-minute rule */

/* One row per horizon, three big targets each. No typing, no weights — five
   taps is the entire commitment this screen asks for. */
.horizon {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap; padding: var(--sp-3) var(--sp-4);
}
.horizon--done { border-color: var(--line-strong); }
.horizon__when { font-size: var(--text-base); }
.horizon__feels { display: flex; gap: var(--sp-2); }

.feel {
  inline-size: 2.75rem; block-size: 2.75rem;   /* comfortably past the 44px touch floor */
  display: grid; place-items: center; cursor: pointer;
  border-radius: var(--radius-full);
  background: var(--surface); color: var(--text-faint);
  border: 1px solid var(--line);
}
.feel:hover { border-color: var(--line-strong); }
.feel--on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.feel:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The shape, drawn. Someone who sees a line starting high and ending low has
   understood "buying comfort on credit" before reading a word of the copy. */
.spark { inline-size: 100%; block-size: 5rem; margin-block: var(--sp-3); overflow: visible; }
.spark__mid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 3; }
.spark__line { fill: none; stroke: currentColor; stroke-width: 3; stroke-linejoin: round; stroke-linecap: round; }
.spark__dot { fill: currentColor; }
.verdict--ok .spark { color: var(--calm); }
.verdict--tight .spark { color: var(--warn); }
.verdict--no .spark { color: var(--danger); }

/* ---------------------------------------------------------------- nav groups */

/* Fifteen equal-weight links read as a wall. Headings let the eye parse four
   things instead, and they say what each group is FOR rather than listing it. */
.nav__group {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-faint); padding-inline: var(--sp-4);
  margin-block: var(--sp-4) var(--sp-1);
}
.nav__group:first-of-type { margin-block-start: var(--sp-2); }

/* One toggle for everything not yet unlocked. Ten dimmed rows solved "where
   did it go" by creating "what is all this", which is the worse problem. */
.nav__more {
  display: flex; align-items: center; gap: var(--sp-3);
  inline-size: 100%; text-align: start; cursor: pointer;
  padding: var(--sp-3) var(--sp-4); margin-block-start: var(--sp-4);
  background: none; border: 0; color: var(--text-faint);
  font: inherit; font-size: var(--text-sm);
}
.nav__more:hover { color: var(--text); }
.nav__more svg { flex: none; }
.nav__count {
  margin-inline-start: auto; font-family: var(--font-numeric);
  direction: ltr; unicode-bidi: isolate;
}

/* --------------------------------------------------------- the ask box */

/* Asking sits above the unprompted advice. Someone who arrived with a question
   should not scroll past three cards answering questions they did not ask. */
.askbox__form { gap: var(--sp-2); align-items: stretch; }
.askbox__field { flex: 1 1 14rem; min-inline-size: 0; }

/* A secondary answer is dimmer, not smaller — the words still need reading. */
.counsel--secondary { opacity: 0.8; border-inline-start-color: var(--line-strong); }

/* ================================================================== welcome
   The first screen someone sees after being chosen. Centred and narrow — this
   is the one moment in the app that is read rather than operated. */

.welcome {
  min-block-size: 100dvh; display: grid; place-items: center;
  padding: var(--sp-5); background: var(--bg);
}
.welcome__panel { inline-size: min(30rem, 100%); }
.welcome__eyebrow {
  font-size: var(--text-sm); color: var(--accent-text);
  letter-spacing: 0.02em;
}
.welcome__lede { font-size: var(--text-lg); color: var(--text-dim); line-height: 1.5; }

/* The sender's own words carry this screen, so they get the weight. */
.welcome__note {
  margin: 0; padding: var(--sp-4) var(--sp-5);
  border-inline-start: 3px solid var(--accent);
  background: var(--surface); border-radius: var(--radius);
  font-size: var(--text-lg); line-height: 1.5;
}
.welcome__note cite {
  display: block; margin-block-start: var(--sp-3);
  font-style: normal; font-size: var(--text-sm); color: var(--text-faint);
}

.welcome__earned {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  color: var(--text-dim); font-size: var(--text-sm);
}
.welcome__earned svg { flex: none; color: var(--accent); margin-block-start: 2px; }

.welcome__field { font-size: var(--text-lg); padding: var(--sp-4); }

.btn--block { inline-size: 100%; justify-content: center; }

/* ===================================================================== door
   The only way in during the private period, and the first thing anyone who
   hears about newme will see. Centred, narrow, and quiet — the scarcity is
   real, so nothing here has to sell it. */

.door {
  min-block-size: 100dvh; display: grid; place-items: center;
  padding: var(--sp-5); background: var(--bg);
}
.door__panel { inline-size: min(28rem, 100%); text-align: center; }

.door__mark {
  font-size: var(--text-lg); font-weight: 700; letter-spacing: -0.03em;
  color: var(--accent-text); margin-block-end: var(--sp-5);
}
.door__title { font-size: var(--text-2xl); letter-spacing: -0.03em; }
.door__lede { color: var(--text-dim); font-size: var(--text-base); line-height: 1.55; }

.door__form { display: flex; flex-direction: column; gap: var(--sp-3); margin-block-start: var(--sp-4); }

/* Monospaced and wide-tracked so a code read down a phone can be checked
   character by character against what is on screen. */
.door__code {
  font-family: var(--font-numeric); font-size: var(--text-xl);
  letter-spacing: 0.14em; text-align: center; text-transform: uppercase;
  padding: var(--sp-4); direction: ltr;
}

.door__error {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  color: var(--warn); font-size: var(--text-sm);
}
.door__error svg { flex: none; }

.door__rule { inline-size: 100%; border: 0; border-block-start: 1px solid var(--line); margin-block: var(--sp-5) 0; }
.door__how { color: var(--text-dim); font-size: var(--text-sm); line-height: 1.6; }
.door__note { color: var(--text-faint); font-size: var(--text-xs); line-height: 1.6; }

/* =============================================================== invitations
   The growth loop, styled to stay a gift rather than become a task. No
   progress bar toward a referral reward, no share sheet, no leaderboard. */

.invite__held { text-align: center; }
.invite__count {
  font-family: var(--font-numeric); font-size: clamp(3rem, 12vw, 4.5rem);
  font-weight: 700; line-height: 1; letter-spacing: -0.05em;
  color: var(--text-faint);
}
.invite__held--has .invite__count { color: var(--accent); }
.invite__label { font-size: var(--text-lg); font-weight: 600; margin-block: var(--sp-2) var(--sp-3); }

.invite__given--in { border-inline-start: 3px solid var(--accent); }

/* The sender's own words, shown back to them — a month later "what did I say
   to Sara?" is a real question. */
.invite__note {
  border-inline-start: 2px solid var(--line-strong);
  padding-inline-start: var(--sp-3);
  color: var(--text-dim); font-size: var(--text-sm);
}

.invite__coderow { align-items: center; gap: var(--sp-3); }
.invite__code {
  font-family: var(--font-numeric); font-size: var(--text-lg);
  letter-spacing: 0.12em; padding: var(--sp-2) var(--sp-3);
  background: var(--surface-hover); border-radius: var(--radius-sm);
  user-select: all; direction: ltr;
}

.invite__stat { font-size: var(--text-sm); color: var(--text-dim); }
.invite__privacy { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--text-xs); }
.invite__privacy svg { flex: none; }
