/* Neulova React dev port — "Yarn Loop" design system (Tactile Bauhaus).
 * Tokens ported from app/theme.dart. Light + dark themes via CSS variables. */

:root {
  /* Follow the app's theme for form controls, scrollbars and the browser UI. */
  color-scheme: light;

  /* Safe-area insets — `viewport-fit=cover` lets the app paint edge-to-edge
     (under the notch / home indicator); these keep UI clear of the hardware. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);

  --primary: #006767;
  --on-primary: #ffffff;
  --primary-container: #188181;
  --on-primary-container: #f3fffe;
  --secondary: #5a5b84;
  --on-secondary: #ffffff;
  --secondary-container: #cecdfd;
  --on-secondary-container: #56567f;
  --tertiary: #7a5500;
  --tertiary-container: #9a6c00;
  --on-tertiary-container: #ffdfaa;
  --error: #ba1a1a;
  --error-container: #ffdad6;
  --surface: #fcf8ff;
  --surface-dim: #dcd8e1;
  --surface-lowest: #ffffff;
  --surface-low: #f6f2fb;
  --surface-container: #f0ecf5;
  --surface-high: #eae7f0;
  --surface-highest: #e5e1ea;
  --on-surface: #1b1b21;
  --on-surface-variant: #464652;
  --outline: #777684;
  --outline-variant: #c7c5d4;
  --brand: #00a99d;
  --active-row: #006767;
  --chart-boundary: #3a5068;
  --axis-label: #5b5b69;
  --scrim: rgba(0, 0, 0, 0.45);
  --hover: rgba(0, 0, 0, 0.06);

  /* ── Motion system ─────────────────────────────────────────────────── */
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
  --ease-out-back: cubic-bezier(0.34, 1.42, 0.64, 1);
  --ease-spring: cubic-bezier(0.22, 1.2, 0.36, 1);
  --dur-fast: 130ms;
  --dur-med: 220ms;
  --dur-slow: 340ms;
  --dur-slower: 480ms;
  --shadow-lift: 0 12px 28px rgba(0, 0, 0, 0.16);
  --focus-ring: 0 0 0 3px rgba(0, 103, 103, 0.35);
}

:root[data-theme='dark'] {
  color-scheme: dark;

  --primary: #7bd5d5;
  --on-primary: #003737;
  --primary-container: #004f4f;
  --on-primary-container: #98f2f1;
  --secondary: #cecdfd;
  --on-secondary: #2b2c50;
  --secondary-container: #424368;
  --on-secondary-container: #cecdfd;
  --tertiary: #f9bc4c;
  --tertiary-container: #5c4100;
  --on-tertiary-container: #ffdeab;
  --error: #ffb4ab;
  --error-container: #93000a;
  --surface: #131318;
  --surface-dim: #131318;
  --surface-lowest: #0d0d12;
  --surface-low: #1b1b21;
  --surface-container: #1f1f27;
  --surface-high: #2a2a32;
  --surface-highest: #35353d;
  --on-surface: #e5e1ea;
  --on-surface-variant: #c7c5d4;
  --outline: #90909c;
  --outline-variant: #44444f;
  --brand: #00a99d;
  --active-row: #7bd5d5;
  --chart-boundary: #9fb6c4;
  --axis-label: #c7c5d4;
  --scrim: rgba(0, 0, 0, 0.6);
  --hover: rgba(255, 255, 255, 0.08);
  --shadow-lift: 0 12px 30px rgba(0, 0, 0, 0.55);
  --focus-ring: 0 0 0 3px rgba(123, 213, 213, 0.45);
}

* {
  box-sizing: border-box;
  /* No 300 ms double-tap-zoom delay on controls; pinch-zoom still works.
     Elements that own a gesture (grids, pan/zoom, crop handles) override
     this with `touch-action: none` — class rules and inline styles win. */
  touch-action: manipulation;
  /* Kill the grey/blue flash on tap: the UI ships its own press feedback. */
  -webkit-tap-highlight-color: transparent;
}

html {
  margin: 0;
  padding: 0;
  height: 100%;
  /* Never let mobile browsers inflate text (e.g. iOS landscape). */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Stop pull-to-refresh and rubber-band on the root scroller. */
  overscroll-behavior: none;
  background: var(--surface);
}

body {
  margin: 0;
  padding: 0;
  height: 100%;
  overscroll-behavior: none;
  font-family: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  background: var(--surface);
  color: var(--on-surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#root,
.app {
  /* 100vh first as a fallback, then dvh where supported: dvh tracks the mobile
     URL bar, so the layout never jumps when it slides in or out. */
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface);
  color: var(--on-surface);
}

.screen--dark,
.screen--black {
  background: #000;
  color: #fff;
}

.screen__body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  /* Momentum scrolling + don't chain the scroll to the page behind. */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.screen__body--column {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.spacer {
  flex: 1;
}

.gap-24 {
  height: 24px;
}

.center-pad {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
}

.list-pad {
  padding: 20px;
  /* Clear the floating nav + the home indicator. */
  padding-bottom: calc(110px + var(--safe-bottom));
  padding-left: calc(20px + var(--safe-left));
  padding-right: calc(20px + var(--safe-right));
}

/* ── icons ──────────────────────────────────────────────────────────── */
.material-symbols-rounded {
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  font-size: 24px;
  line-height: 1;
  user-select: none;
  display: inline-block;
  font-feature-settings: 'liga';
  -webkit-font-feature-settings: 'liga';
}

.icon {
  flex: none;
}

/* ── app bar ────────────────────────────────────────────────────────── */
.appbar {
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: 56px;
  /* Keep the bar out from under the status bar / notch. */
  padding: 0 4px;
  padding-top: var(--safe-top);
  padding-left: calc(4px + var(--safe-left));
  padding-right: calc(4px + var(--safe-right));
  background: var(--surface);
  color: var(--on-surface);
  flex: none;
  z-index: 20;
}

.appbar--transparent {
  background: transparent;
}

.appbar--dark {
  color: #fff;
}

.appbar__leading,
.appbar__actions {
  display: flex;
  align-items: center;
  color: inherit;
}

.appbar__actions {
  margin-left: auto;
}

.appbar__title {
  font-size: 20px;
  font-weight: 800;
  color: var(--primary);
  padding: 0 6px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  min-width: 0;
}

.appbar--dark .appbar__title {
  color: #fff;
}

.appbar--center .appbar__title {
  flex: 1;
  justify-content: center;
}

.appbar--center .appbar__leading + .appbar__title {
  justify-content: center;
}

.appbar__rename {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  border-radius: 8px;
  padding: 2px 4px;
  min-width: 0;
}

.appbar__rename:hover {
  background: var(--hover);
}

.appbar__rename-text {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.brand-logo {
  height: 26px;
  width: auto;
  display: block;
}

@media (min-width: 600px) {
  .brand-logo {
    height: 22px;
  }
}

@media (min-width: 900px) {
  .brand-logo {
    height: 20px;
  }
}

/* ── buttons ────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  border: none;
  border-radius: 24px;
  padding: 12px 20px;
  cursor: pointer;
  transition: filter 0.12s ease, background 0.12s ease;
}

.btn:disabled {
  opacity: 0.45;
  cursor: default;
}

.btn--filled {
  background: var(--primary);
  color: var(--on-primary);
}

.btn--filled:hover:not(:disabled) {
  filter: brightness(1.08);
}

.btn--danger {
  background: var(--error);
  color: #fff;
}

.btn--tonal {
  background: var(--secondary-container);
  color: var(--on-secondary-container);
  padding: 10px 16px;
}

.btn--outlined {
  background: transparent;
  color: var(--secondary);
  border: 2px solid var(--outline);
}

.btn--text {
  background: transparent;
  color: var(--primary);
  padding: 8px 12px;
}

.btn--on-dark.btn--outlined {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.5);
}

.textbtn {
  background: none;
  border: none;
  color: var(--primary);
  font-family: inherit;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  padding: 6px 10px;
  border-radius: 8px;
}

.textbtn:hover {
  background: var(--hover);
}

.tactile {
  position: relative;
  border: none;
  border-radius: 24px;
  background: var(--primary);
  color: var(--on-primary);
  font-family: inherit;
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 4px 0 rgba(0, 0, 0, 0.28);
  transition: transform 0.07s ease, box-shadow 0.07s ease, filter 0.12s ease;
}

.tactile__content {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 24px;
}

.tactile:active:not(:disabled) {
  transform: translateY(3px);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.28);
}

.tactile:disabled {
  opacity: 0.5;
  cursor: default;
}

.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px is the recommended minimum touch target (Apple HIG / Material). */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: inherit;
  cursor: pointer;
  flex: none;
}

.iconbtn:hover:not(:disabled) {
  background: var(--hover);
}

.iconbtn:disabled {
  opacity: 0.35;
  cursor: default;
}

.fab {
  position: fixed;
  right: calc(20px + var(--safe-right));
  bottom: calc(88px + var(--safe-bottom));
  z-index: 500;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border: none;
  border-radius: 20px;
  padding: 14px 20px;
  background: var(--primary);
  color: var(--on-primary);
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
}

.fab:hover {
  filter: brightness(1.08);
}

/* ── bottom navigation ──────────────────────────────────────────────── */
.bottom-nav {
  flex: none;
  border-top: 2px solid var(--outline-variant);
  background: var(--surface-container);
  /* Rounded-corner / gesture-bar clearance. */
  padding-bottom: var(--safe-bottom);
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
}

.bottom-nav__inner {
  margin: 0 auto;
  max-width: 520px;
  height: 64px;
  display: flex;
}

@media (min-width: 600px) {
  .bottom-nav__inner {
    height: 56px;
  }
}

.bottom-nav__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: none;
  background: transparent;
  color: var(--on-surface-variant);
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
}

.bottom-nav__item.is-active {
  color: var(--brand);
  font-weight: 700;
}

/* ── cards / lists ──────────────────────────────────────────────────── */
.card {
  background: var(--surface-low);
  border: 2px solid var(--outline-variant);
  border-radius: 16px;
  padding: 16px;
  margin-bottom: 12px;
}

.card[onclick],
.card.clickable {
  cursor: pointer;
}

.section-title {
  color: var(--brand);
  font-size: 26px;
  font-weight: 700;
  margin: 0 0 16px;
}

.section-title--small {
  font-size: 18px;
  font-weight: 700;
  color: var(--on-surface);
  margin: 8px 0;
}

.empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 32px;
  text-align: center;
  color: var(--on-surface);
}

.empty-state__title {
  font-size: 26px;
  font-weight: 700;
  color: var(--brand);
  margin: 0;
}

.empty-state__text {
  margin: 0;
  color: var(--on-surface);
  max-width: 420px;
}

.empty-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 24px;
  text-align: center;
}

/* project card */
.project-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin: -8px 0 0;
}

.project-card__name {
  margin: 8px 0 0;
  font-size: 17px;
  font-weight: 700;
  flex: 1;
  cursor: pointer;
}

.project-card__desc {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--on-surface-variant);
}

.project-card__meta {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
  font-size: 13px;
  color: var(--on-surface-variant);
}

.project-card__progress {
  margin-top: 8px;
}

.chart-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
}

.chart-tile__main {
  flex: 1;
  min-width: 0;
}

.chart-tile__name {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 700;
  max-width: 100%;
}

.chart-tile__name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chart-tile__sub {
  font-size: 13px;
  color: var(--on-surface-variant);
}

/* ── inputs ─────────────────────────────────────────────────────────── */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  margin-bottom: 8px;
}

.field__label {
  font-size: 13px;
  font-weight: 600;
  color: var(--on-surface-variant);
}

.field__input {
  width: 100%;
  background: var(--surface-low);
  border: 2px solid var(--outline);
  border-radius: 16px;
  padding: 12px 14px;
  font-family: inherit;
  font-size: 15px;
  color: var(--on-surface);
  outline: none;
}

.field__input:focus {
  border-color: var(--primary);
}

/* iOS Safari zooms the entire page when a focused control renders under 16px;
   bump inputs on iOS only so the desktop/Android metrics stay unchanged. */
@supports (-webkit-touch-callout: none) {
  .field__input,
  input,
  select,
  textarea {
    font-size: 16px;
  }
}

.field__row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.field__row .field__input {
  flex: 1;
}

.dialog__body--fields .field {
  margin-bottom: 14px;
}

/* ── progress / spinners ────────────────────────────────────────────── */
.progress {
  height: 8px;
  border-radius: 8px;
  background: var(--surface-highest);
  overflow: hidden;
}

.progress__fill {
  height: 100%;
  border-radius: 8px;
  background: var(--primary);
  transition: width 0.2s ease;
}

.spinner {
  display: inline-block;
  border-radius: 50%;
  border: 3px solid var(--outline-variant);
  border-top-color: var(--primary);
  animation: spin 0.9s linear infinite;
}

.spinner--light {
  border-color: rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ── dialogs / sheets / snackbars ───────────────────────────────────── */
.modal-layer {
  position: fixed;
  inset: 0;
  /* Children opt back in (backdrop/dialog/sheet). Keeps pass-through
     sheets from blocking the page behind them. */
  pointer-events: none;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  pointer-events: auto;
  background: var(--scrim);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.dialog {
  background: var(--surface-low);
  color: var(--on-surface);
  border-radius: 24px;
  padding: 20px;
  width: 100%;
  max-width: 400px;
  max-height: 80vh;
  max-height: 80dvh;
  overflow: auto;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
}

.dialog--picker {
  max-width: 400px;
}

.dialog__title {
  margin: 0 0 12px;
  font-size: 18px;
  font-weight: 700;
}

.dialog__body {
  margin-bottom: 8px;
}

.dialog__message {
  margin: 0 0 8px;
  line-height: 1.5;
}

.dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
}

.sheet-backdrop {
  position: absolute;
  inset: 0;
  pointer-events: auto;
  background: var(--scrim);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.sheet {
  background: var(--surface-low);
  color: var(--on-surface);
  border-radius: 24px 24px 0 0;
  width: 100%;
  max-width: 520px;
  max-height: 82vh;
  max-height: 82dvh;
  overflow: auto;
  padding: 10px 16px calc(20px + var(--safe-bottom));
  box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.35);
}

.sheet__handle {
  width: 36px;
  height: 4px;
  border-radius: 2px;
  background: var(--outline-variant);
  margin: 6px auto 10px;
}

/* Non-modal sheet (palette editor): the page behind stays interactive. */
.sheet-backdrop--pass {
  background: transparent;
  pointer-events: none;
}

.sheet-backdrop--pass .sheet {
  pointer-events: auto;
  box-shadow: 0 -8px 34px rgba(0, 0, 0, 0.4);
}

.sheet--palette {
  max-height: 62vh;
  max-height: 62dvh;
}

.sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sheet__title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
}

.sheet__hint {
  margin: 6px 0 2px;
  font-size: 13px;
  color: var(--on-surface-variant);
}

.sheet__hint--small {
  font-size: 11px;
}

.sheet__empty {
  padding: 16px 0;
  color: var(--on-surface-variant);
}

.snack-layer {
  position: fixed;
  left: 50%;
  bottom: calc(96px + var(--safe-bottom));
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(92vw, 520px);
  z-index: 3000;
  pointer-events: none;
}

.snack {
  pointer-events: auto;
  background: var(--on-surface);
  color: var(--surface);
  border-radius: 10px;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  font-size: 14px;
}

.snack__text {
  flex: 1;
}

.snack__action {
  background: none;
  border: none;
  color: var(--brand);
  font-family: inherit;
  font-weight: 700;
  cursor: pointer;
  font-size: 14px;
}

/* ── HSV picker ─────────────────────────────────────────────────────── */
.picker {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.picker__square {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  max-height: 320px;
  border-radius: 12px;
  background: linear-gradient(to top, #000, rgba(0, 0, 0, 0)), linear-gradient(to right, #fff, rgba(255, 255, 255, 0)),
    var(--picker-hue, #f00);
  cursor: crosshair;
  touch-action: none;
}

.picker__handle {
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--on-surface);
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: transparent;
}

.picker__hue-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.picker__hue-label {
  font-weight: 700;
}

.picker__hue {
  flex: 1;
  appearance: none;
  height: 12px;
  border-radius: 6px;
  background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
  outline: none;
}

.picker__preview-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.picker__preview {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  border: 2px solid var(--outline);
}

.picker__hex {
  font-weight: 600;
}

/* ── palette / colorwork ────────────────────────────────────────────── */
.pswatch {
  border-radius: 50%;
  border-style: solid;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.pswatch--tap {
  cursor: pointer;
}

.palette-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
}

.palette-row__col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}

.palette-row__caption {
  font-size: 8px;
  color: var(--on-surface-variant);
}

.palette-row__info {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.palette-row__code {
  font-weight: 700;
}

.palette-row__count {
  font-size: 12px;
  color: var(--on-surface-variant);
}

.cell-picker-sheet__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px 0;
}

.assign-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: 12px;
  cursor: pointer;
}

.assign-tile:hover {
  background: var(--hover);
}

.assign-tile__code {
  font-size: 10px;
}

.assign-tile__count {
  font-size: 9px;
  color: var(--on-surface-variant);
}

/* dropdown menus */
.menu {
  position: relative;
  display: inline-flex;
}

.menu__trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: none;
  border-radius: 24px;
  padding: 12px 16px;
  font-family: inherit;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
}

.menu__backdrop {
  position: fixed;
  inset: 0;
  z-index: 900;
}

.menu__popup {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 950;
  min-width: 240px;
  background: var(--surface-low);
  border: 2px solid var(--outline-variant);
  border-radius: 12px;
  padding: 6px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.3);
}

.menu__popup--right {
  left: auto;
  right: 0;
}

.menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  border-radius: 8px;
  padding: 10px 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--on-surface);
  cursor: pointer;
  text-align: left;
}

.menu__item:hover:not(:disabled) {
  background: var(--hover);
}

.menu__item:disabled {
  opacity: 0.45;
  cursor: default;
}

.menu__code {
  font-weight: 700;
}

.menu__count {
  margin-left: auto;
  font-size: 12px;
  color: var(--on-surface-variant);
}

.menu__empty {
  padding: 10px;
  font-size: 13px;
  color: var(--on-surface-variant);
  max-width: 260px;
}

.menu__divider {
  height: 2px;
  background: var(--outline-variant);
  margin: 6px 4px;
}

/* ── editor ─────────────────────────────────────────────────────────── */
.editor-info {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  background: var(--surface-low);
  font-size: 14px;
  flex: none;
  flex-wrap: wrap;
}

.editor-info__dims {
  font-weight: 700;
}

.editor-info__cell {
  color: var(--primary);
  font-weight: 600;
}

.editor-info__hint {
  color: var(--on-surface-variant);
  font-size: 13px;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
}

.badge--tertiary {
  background: var(--tertiary-container);
  color: var(--on-tertiary-container);
}

.editor-selbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  background: var(--primary-container);
  color: var(--on-primary-container);
  flex: none;
  flex-wrap: wrap;
}

.editor-selbar__count {
  font-weight: 700;
}

.editor-selbar .btn--text {
  color: var(--on-primary-container);
}

.editor-selbar .btn--filled {
  background: var(--on-primary-container);
  color: var(--primary-container);
}

.editor-grid-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  padding: 8px;
}

.editor-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  border-top: 2px solid var(--outline-variant);
  background: var(--surface-container);
  flex: none;
}

/* editor grid */
.egrid {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.egrid__header {
  display: flex;
  height: 20px;
  align-items: center;
}

.egrid__colnum {
  width: 46px;
  flex: none;
  text-align: center;
  font-size: 9px;
  color: var(--axis-label);
}

.egrid__body {
  display: flex;
  align-items: flex-start;
}

.egrid__gutter {
  display: flex;
  flex-direction: column;
  flex: none;
}

.egrid__rownum {
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 4px;
  font-size: 9px;
  color: var(--axis-label);
}

.egrid__area {
  border-style: solid;
  border-width: 2px;
  touch-action: none;
}

.egrid__area--selecting,
.egrid__area--selecting .ecell {
  cursor: crosshair;
}

.egrid__row {
  display: flex;
}

.ecell {
  position: relative;
  height: 44px;
  margin: 1px;
  border-style: solid;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  flex: none;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
}

.ecell__crop {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  overflow: hidden;
}

.crop-img {
  width: 100%;
  height: 100%;
  object-fit: fill;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

.ecell__sel {
  position: absolute;
  inset: 0;
  opacity: 0.3;
  border-radius: 3px;
  pointer-events: none;
}

.ecell__span {
  position: absolute;
  right: 2px;
  bottom: 1px;
  font-size: 8px;
  font-weight: 700;
  color: var(--on-surface-variant);
  pointer-events: none;
}

/* ── pan / zoom ─────────────────────────────────────────────────────── */
.panzoom {
  position: relative;
  overflow: hidden;
  flex: 1;
  min-height: 0;
  min-width: 0;
  background: var(--surface-lowest);
  border: 1px solid var(--outline-variant);
  border-radius: 8px;
}

.panzoom__content {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  will-change: transform;
}

/* ── tracker ────────────────────────────────────────────────────────── */
.tracker-status {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px 6px;
  flex: none;
}

.tracker-status__label {
  font-size: 17px;
  font-weight: 700;
  white-space: nowrap;
}

.tracker-status__bar {
  flex: 1;
}

.tracker-canvas {
  flex: 1;
  min-height: 0;
  display: flex;
  padding: 0 8px 8px;
}

.tgrid {
  flex: 1;
  display: flex;
  min-height: 0;
  min-width: 0;
}

.tgrid__boundary {
  position: absolute;
  border-style: solid;
  border-width: 2px;
  border-radius: 4px;
}

.tgrid__row {
  position: absolute;
}

.tgrid__active {
  position: absolute;
  inset: 0;
  border-style: solid;
  border-width: 2.5px;
  border-radius: 6px;
  pointer-events: none;
}

.tgrid__rowcells {
  display: flex;
  height: 100%;
}

.tcell {
  position: relative;
  flex: none;
}

.tcell__inner {
  position: absolute;
  inset: 0;
  border-style: solid;
  border-radius: 3px;
  overflow: hidden;
}

.tcell__crop {
  position: absolute;
  inset: 0;
}

.tcell__done {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tgrid__axis {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  pointer-events: none;
}

.tracker-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
}

.tracker-tile__photo {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 6px;
}

.tracker-tile__main {
  flex: 1;
  min-width: 0;
}

.tracker-tile__name {
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tracker-tile__sub {
  font-size: 12px;
  color: var(--on-surface-variant);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tracker-project__name {
  font-weight: 700;
  margin-bottom: 6px;
}

.tracker-project__empty {
  font-size: 13px;
  color: var(--on-surface-variant);
}

.tracker-project__chart {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  border-radius: 10px;
  padding: 10px;
  font-family: inherit;
  font-size: 14px;
  color: var(--on-surface);
  cursor: pointer;
  text-align: left;
}

.tracker-project__chart:hover {
  background: var(--hover);
}

.tracker-project__chartname {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tracker-project__dim {
  font-size: 12px;
  color: var(--on-surface-variant);
}

.voice-help__row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin: 10px 0;
}

.voice-help__label {
  font-weight: 700;
}

.voice-help__words {
  font-size: 13px;
  color: var(--on-surface-variant);
}

.voice-help__note {
  font-size: 12px;
  color: var(--on-surface-variant);
  margin: 12px 0 0;
}

/* ── scanner ────────────────────────────────────────────────────────── */
.scanner-body {
  position: relative;
  flex: 1;
  min-height: 0;
  background: #000;
  display: flex;
  flex-direction: column;
}

.cam-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.cam-frame {
  position: relative;
  overflow: hidden;
  background: #000;
}

.cam-frame video {
  object-fit: cover;
  display: block;
}

.scanner-hint {
  position: absolute;
  bottom: calc(132px + var(--safe-bottom));
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 14px;
  white-space: nowrap;
}

.shutter {
  position: absolute;
  bottom: calc(36px + var(--safe-bottom));
  left: 50%;
  transform: translateX(-50%);
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 4px solid #fff;
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.shutter:active {
  background: rgba(255, 255, 255, 0.4);
}

.scanner-error-text {
  color: rgba(255, 255, 255, 0.7);
  font-size: 12px;
  max-width: 340px;
  margin: 0;
}

.upload-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.upload-overlay__card {
  background: var(--surface-low);
  color: var(--on-surface);
  border-radius: 16px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  min-width: 260px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}

.upload-overlay__card p {
  margin: 0;
  font-weight: 600;
}

/* ── scan processing (image + cyan matrix sweep) ────────────────────── */
.scan-proc {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #02090d;
  animation: fadeIn 0.25s ease;
}

.scan-proc__frame {
  position: relative;
  overflow: hidden;
  border-radius: 10px;
  background: #04121a;
  box-shadow: 0 0 0 1px rgba(90, 230, 255, 0.35), 0 14px 60px rgba(0, 60, 90, 0.55);
}

.scan-proc__frame img {
  width: 100%;
  height: 100%;
  object-fit: fill;
  display: block;
}

.scan-proc__fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.scan-proc__status {
  position: absolute;
  left: 50%;
  bottom: calc(34px + var(--safe-bottom));
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  background: rgba(4, 22, 30, 0.82);
  border: 1px solid rgba(90, 230, 255, 0.4);
  color: #d8fbff;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* ── crop & rotate ──────────────────────────────────────────────────── */
.crop-stage {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: hidden;
  position: relative;
  background: var(--surface-container);
}

.crop-frame {
  position: relative;
  line-height: 0;
  flex: none;
}

.crop-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.crop-dim {
  position: absolute;
  border: 2px solid #fff;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.45);
  cursor: move;
  touch-action: none;
}

.crop-handle {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.85);
  border: 2px solid #2196f3;
  touch-action: none;
}

.crop-handle--tl {
  left: -11px;
  top: -11px;
  cursor: nwse-resize;
}

.crop-handle--tr {
  right: -11px;
  top: -11px;
  cursor: nesw-resize;
}

.crop-handle--bl {
  left: -11px;
  bottom: -11px;
  cursor: nesw-resize;
}

.crop-handle--br {
  right: -11px;
  bottom: -11px;
  cursor: nwse-resize;
}

/* ── swatches ───────────────────────────────────────────────────────── */
.swatch-entry {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  cursor: pointer;
}

.swatch-entry__preview {
  width: 112px;
  height: 88px;
  flex: none;
}

.swatch-preview {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface-high);
}

.swatch-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.swatch-preview__tint,
.swatch-preview__cell {
  position: absolute;
  pointer-events: none;
}

.swatch-preview__cell img {
  width: 100%;
  height: 100%;
  object-fit: fill;
  display: block;
}

.swatch-entry__main {
  flex: 1;
  min-width: 0;
}

.swatch-entry__name {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 700;
  cursor: pointer;
  border-radius: 6px;
  max-width: 100%;
}

.swatch-entry__name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.swatch-entry__chart {
  font-size: 13px;
  color: var(--on-surface-variant);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.swatch-entry__range,
.swatch-entry__meta {
  font-size: 12px;
  color: var(--on-surface-variant);
}

.chart-chooser__list {
  display: flex;
  flex-direction: column;
  padding-bottom: 12px;
}

.chart-chooser__item {
  display: flex;
  align-items: center;
  gap: 12px;
  background: none;
  border: none;
  border-radius: 10px;
  padding: 12px;
  font-family: inherit;
  font-size: 15px;
  color: var(--on-surface);
  cursor: pointer;
  text-align: left;
}

.chart-chooser__item:hover {
  background: var(--hover);
}

.chart-chooser__name {
  flex: 1;
  font-weight: 600;
}

.chart-chooser__dim {
  font-size: 12px;
  color: var(--on-surface-variant);
}

.source-chooser {
  display: flex;
  flex-direction: column;
  padding: 4px 0 8px;
}

.source-chooser__item {
  display: flex;
  align-items: center;
  gap: 14px;
  background: none;
  border: none;
  border-radius: 10px;
  padding: 14px 12px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  color: var(--on-surface);
  cursor: pointer;
  text-align: left;
}

.source-chooser__item:hover {
  background: var(--hover);
}

/* swatch picker grid */
.picker-info {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 12px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid var(--outline-variant);
  background: var(--surface-container);
  font-size: 13px;
  flex: none;
}

.picker-info.is-selecting {
  border-color: var(--primary);
  background: var(--primary-container);
  color: var(--on-primary-container);
}

.picker-info__text {
  flex: 1;
}

.picker-info__count {
  font-weight: 700;
}

.picker-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 0 12px 12px;
}

.pgr {
  position: relative;
  touch-action: none;
}

.pcell {
  position: absolute;
  pointer-events: none;
}

.pcell img {
  width: 100%;
  height: 100%;
  object-fit: fill;
  display: block;
  padding: 1px;
}

.pgr__sel {
  position: absolute;
  border-style: solid;
  border-width: 2px;
  pointer-events: none;
}

.picker-footer {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px 16px;
  flex: none;
}

.picker-footer__count {
  font-weight: 700;
  flex: 1;
}

/* ── settings ───────────────────────────────────────────────────────── */
.settings-wrap {
  max-width: 720px;
  margin: 0 auto;
  padding: 20px;
  padding-bottom: 80px;
}

.settings-section {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  margin: 28px 0 10px;
}

.settings-advanced {
  padding: 0;
  overflow: hidden;
}

.settings-advanced__head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: none;
  border: none;
  padding: 16px;
  font-family: inherit;
  color: var(--on-surface);
  cursor: pointer;
  text-align: left;
}

.settings-advanced__titles {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.settings-advanced__title {
  font-weight: 700;
  font-size: 16px;
}

.settings-advanced__sub {
  font-size: 12px;
  color: var(--on-surface-variant);
}

.settings-advanced__body {
  padding: 0 16px 16px;
}

.settings-label {
  font-weight: 700;
  font-size: 14px;
  margin-bottom: 8px;
}

.settings-test {
  width: 100%;
  margin-top: 4px;
}

.settings-testresult {
  margin: 10px 0 0;
  font-size: 13px;
}

.settings-testresult.is-ok {
  color: var(--primary);
}

.settings-testresult.is-error {
  color: var(--error);
  word-break: break-word;
}

.settings-row {
  display: flex;
  gap: 12px;
}

.settings-choice {
  flex: 1;
  background: var(--surface-container);
  color: var(--on-surface-variant);
}

.settings-choice.is-active {
  background: var(--primary);
  color: var(--on-primary);
}

.partners {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.partner {
  max-width: 300px;
  margin: 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
}

.partner__frame {
  width: 100%;
  border: 1px solid var(--outline-variant);
  border-radius: 12px;
  padding: 8px 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.partner__frame img {
  height: 48px;
  max-width: 100%;
  object-fit: contain;
}

.partner__label {
  font-size: 12px;
  color: var(--on-surface-variant);
  text-align: center;
}

.team {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.team-contact {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.team-contact__role {
  font-size: 13px;
  color: var(--on-surface-variant);
}

.team-contact__name {
  font-weight: 700;
}

.team-contact__email {
  color: var(--primary);
  font-size: 14px;
  text-decoration: none;
}

.settings-about__name {
  font-weight: 700;
  font-size: 16px;
}

.settings-about__version {
  font-size: 12px;
  color: var(--on-surface-variant);
  margin: 2px 0 10px;
}

.settings-about__text {
  margin: 0;
  line-height: 1.5;
}

.settings-footer {
  margin-top: 20px;
  display: flex;
  justify-content: center;
}

/* ── misc ───────────────────────────────────────────────────────────── */
.ref-image {
  border-radius: 12px;
  overflow: hidden;
  margin-bottom: 16px;
}

.ref-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-thumb {
  background: var(--outline-variant);
  border-radius: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

/* ═══════════════════════════════════════════════════════════════════════
 * MOTION LAYER — "Yarn Loop" micro-interactions & transitions
 *
 * Everything below is pure CSS and degrades to a static (but identical)
 * layout. Entrance animations use `backwards` fill so that once they end the
 * element returns to its base styles — this keeps hover transforms, fixed
 * positioning and measurement-based layouts working exactly as before.
 * ===================================================================== */

/* ── keyframes ──────────────────────────────────────────────────────── */
/* Entrance keyframes animate transform ONLY. Content stays legible even if
   the timeline is paused (e.g. a tab opened in the background), which
   opacity fades would not guarantee. */
@keyframes riseIn {
  from { transform: translateY(10px); }
  to { transform: translateY(0); }
}

@keyframes dropIn {
  from { transform: translateY(-10px); }
  to { transform: translateY(0); }
}

@keyframes popIn {
  from { transform: scale(0.95); }
  to { transform: scale(1); }
}

@keyframes backdropIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes dialogIn {
  from { opacity: 0; transform: translateY(14px) scale(0.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes sheetIn {
  from { opacity: 0.35; transform: translateY(36px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes menuIn {
  from { opacity: 0; transform: translateY(-6px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes snackIn {
  from { opacity: 0; transform: translateY(14px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes fabIn {
  from { transform: translateY(16px) scale(0.9); }
  to { transform: translateY(0) scale(1); }
}

@keyframes progressShine {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}

@keyframes rowPulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--active-row) 0%, transparent); }
  50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--active-row) 32%, transparent); }
}

@keyframes donePop {
  0% { opacity: 0; transform: scale(0.3); }
  60% { opacity: 1; transform: scale(1.14); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes floaty {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

@keyframes drawLine {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@keyframes shutterPulse {
  from { opacity: 0.65; transform: scale(0.86); }
  to { opacity: 0; transform: scale(1.24); }
}

/* ── 1. Screen + bar entrances ──────────────────────────────────────── */
/* Note: no transform on .screen itself — that would create a containing
   block and displace the fixed FAB / snack layers. */
.appbar { animation: dropIn var(--dur-slow) var(--ease-emphasized) backwards; }

/* Column screens (tracker) reveal their sections in sequence. */
.screen__body--column > * { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; }
.screen__body--column > *:nth-child(2) { animation-delay: 70ms; }
.screen__body--column > *:nth-child(3) { animation-delay: 140ms; }
.screen__body--column > *:nth-child(4) { animation-delay: 210ms; }

/* Editor chrome drops in with the canvas. */
.editor-info,
.editor-selbar { animation: dropIn var(--dur-slow) var(--ease-emphasized) backwards; }
.editor-grid-wrap,
.editor-actions { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; }
.editor-grid-wrap { animation-delay: 40ms; }
.editor-actions { animation-delay: 80ms; }
.egrid { animation: popIn var(--dur-slow) var(--ease-emphasized) backwards; animation-delay: 60ms; }

/* ── 2. Staggered list / settings reveals ───────────────────────────── */
.list-pad > *,
.settings-wrap > * { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; }

.list-pad > *:nth-child(1), .settings-wrap > *:nth-child(1) { animation-delay: 0ms; }
.list-pad > *:nth-child(2), .settings-wrap > *:nth-child(2) { animation-delay: 40ms; }
.list-pad > *:nth-child(3), .settings-wrap > *:nth-child(3) { animation-delay: 80ms; }
.list-pad > *:nth-child(4), .settings-wrap > *:nth-child(4) { animation-delay: 120ms; }
.list-pad > *:nth-child(5), .settings-wrap > *:nth-child(5) { animation-delay: 160ms; }
.list-pad > *:nth-child(6), .settings-wrap > *:nth-child(6) { animation-delay: 200ms; }
.list-pad > *:nth-child(7), .settings-wrap > *:nth-child(7) { animation-delay: 240ms; }
.list-pad > *:nth-child(8), .settings-wrap > *:nth-child(8) { animation-delay: 280ms; }
.list-pad > *:nth-child(9), .settings-wrap > *:nth-child(9) { animation-delay: 320ms; }
.list-pad > *:nth-child(10), .settings-wrap > *:nth-child(10) { animation-delay: 360ms; }
.list-pad > *:nth-child(n + 11), .settings-wrap > *:nth-child(n + 11) { animation-delay: 400ms; }

/* Section titles draw a short brand rule underneath. */
.section-title { position: relative; }
.section-title::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -6px;
  height: 3px;
  width: 46px;
  border-radius: 2px;
  background: var(--brand);
  transform-origin: left center;
  animation: drawLine var(--dur-slower) var(--ease-emphasized) backwards;
  animation-delay: 120ms;
}

/* ── 3. Empty & loading states ──────────────────────────────────────── */
.empty-state { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; }
.empty-state .icon { animation: floaty 4.2s ease-in-out infinite; }
.empty-state__title { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; animation-delay: 70ms; }
.empty-state__text { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; animation-delay: 130ms; }
.empty-state .btn,
.empty-state .tactile { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; animation-delay: 190ms; }

.center-pad { animation: riseIn var(--dur-slow) var(--ease-emphasized) backwards; }

/* Deferred cell crops use a flat two-tone placeholder — deliberately NOT
   animated: a cold chart mounts 2000+ of them at once and a per-cell
   animation would thrash the main thread. */
.crop-img--pending {
  background: linear-gradient(100deg, var(--surface-high), var(--surface-highest));
}

/* ── 4. Tactile press / hover feedback ──────────────────────────────── */
.btn {
  transition: transform var(--dur-fast) var(--ease-standard),
    filter var(--dur-fast) var(--ease-standard),
    background var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard);
}
.btn:active:not(:disabled) { transform: scale(0.96); }
.btn--filled:hover:not(:disabled) { box-shadow: 0 6px 18px color-mix(in srgb, var(--primary) 38%, transparent); }

.textbtn { transition: background var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard); }
.textbtn:active { transform: scale(0.95); }

.iconbtn {
  transition: background var(--dur-fast) var(--ease-standard),
    transform var(--dur-fast) var(--ease-standard),
    color var(--dur-fast) var(--ease-standard);
}
.iconbtn:hover:not(:disabled) { transform: scale(1.08); }
.iconbtn:active:not(:disabled) { transform: scale(0.9); }

/* Tactile Bauhaus: lift on hover, collapse on press (unchanged press). */
.tactile:hover:not(:active):not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 6px 0 rgba(0, 0, 0, 0.28);
}

.fab {
  animation: fabIn var(--dur-med) var(--ease-out-back) backwards;
  transition: transform var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-med) var(--ease-standard),
    filter var(--dur-fast) var(--ease-standard);
}
.fab:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0, 0, 0, 0.34); }
.fab:active { transform: translateY(0) scale(0.97); }

/* ── 5. Cards ───────────────────────────────────────────────────────── */
.card {
  transition: transform var(--dur-med) var(--ease-standard),
    box-shadow var(--dur-med) var(--ease-standard),
    border-color var(--dur-med) var(--ease-standard),
    background var(--dur-med) var(--ease-standard);
}

.card.clickable:hover,
.card[onclick]:hover,
.card.chart-tile:hover,
.card.tracker-tile:hover,
.card.swatch-entry:hover,
.card.project-card:hover,
.card.tracker-project:hover,
.card.empty-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
  border-color: var(--primary);
}

/* Simple clickable rows (not cards) get a soft wash. */
.chart-chooser__item,
.source-chooser__item,
.tracker-project__chart,
.menu__item,
.settings-advanced__head {
  transition: background var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard);
}

.appbar__rename { transition: background var(--dur-fast) var(--ease-standard); }

/* ── 6. Bottom navigation ───────────────────────────────────────────── */
.bottom-nav__item { position: relative; transition: color var(--dur-med) var(--ease-standard); }
.bottom-nav__item .material-symbols-rounded { transition: transform var(--dur-med) var(--ease-spring); }
.bottom-nav__item::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 0;
  height: 3px;
  border-radius: 0 0 3px 3px;
  background: var(--brand);
  transform: translateX(-50%);
  transition: width var(--dur-med) var(--ease-emphasized);
}
.bottom-nav__item.is-active::before { width: 44%; }
.bottom-nav__item.is-active .material-symbols-rounded { transform: translateY(-1px) scale(1.14); }
.bottom-nav__item:active .material-symbols-rounded { transform: scale(0.86); }

/* ── 7. Progress + spinners ─────────────────────────────────────────── */
.progress__fill {
  position: relative;
  overflow: hidden;
  transition: width var(--dur-med) var(--ease-emphasized);
}
.progress__fill::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 25%, rgba(255, 255, 255, 0.5) 50%, transparent 75%);
  transform: translateX(-100%);
  animation: progressShine 2.4s var(--ease-standard) infinite;
}

/* ── 8. Overlays: dialogs, sheets, menus, snacks ────────────────────── */
.modal-backdrop { animation: backdropIn var(--dur-fast) ease-out backwards; }
.dialog { animation: dialogIn var(--dur-med) var(--ease-emphasized) backwards; }

.sheet-backdrop { animation: backdropIn var(--dur-fast) ease-out backwards; }
.sheet { animation: sheetIn var(--dur-med) var(--ease-emphasized) backwards; }

.menu__popup {
  transform-origin: top left;
  animation: menuIn var(--dur-fast) ease-out backwards;
}
.menu__popup--right { transform-origin: top right; }

.snack { animation: snackIn var(--dur-med) var(--ease-out-back) backwards; }

.upload-overlay { animation: backdropIn var(--dur-fast) ease-out backwards; }
.upload-overlay__card { animation: popIn var(--dur-med) var(--ease-emphasized) backwards; }

/* ── 9. Editor grid liveliness ──────────────────────────────────────── */
.ecell {
  transition: box-shadow var(--dur-fast) var(--ease-standard),
    border-color var(--dur-fast) var(--ease-standard);
}
.ecell:hover { box-shadow: 0 0 0 2px var(--primary); z-index: 3; }
.egrid__area--selecting .ecell { box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 55%, transparent); }

/* ── 10. Tracker liveliness ─────────────────────────────────────────── */
.tgrid__active { animation: rowPulse 2.2s ease-in-out infinite; }
.tcell__inner {
  transition: background var(--dur-med) var(--ease-standard),
    border-color var(--dur-med) var(--ease-standard);
}
.tcell__done { animation: donePop var(--dur-med) var(--ease-out-back) backwards; }

/* ── 11. Swatches / palette ─────────────────────────────────────────── */
.pswatch--tap { transition: transform var(--dur-fast) var(--ease-spring); }
.pswatch--tap:hover { transform: scale(1.1); }
.assign-tile { transition: background var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-spring); }
.assign-tile:hover { transform: translateY(-2px); }

/* ── 12. Scanner ────────────────────────────────────────────────────── */
.shutter { position: absolute; transition: background var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard); }
.shutter::after {
  content: '';
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.55);
  animation: shutterPulse 2.2s ease-out infinite;
  pointer-events: none;
}
.shutter:active { transform: translateX(-50%) scale(0.94); }
.scanner-hint { animation: riseIn var(--dur-med) var(--ease-emphasized) backwards; }

/* ── 13. Misc ───────────────────────────────────────────────────────── */
.ref-image { animation: fadeIn var(--dur-slow) ease-out backwards; }
.partner__frame { transition: transform var(--dur-med) var(--ease-standard), border-color var(--dur-med) var(--ease-standard); }
.partner__frame:hover { transform: translateY(-2px); border-color: var(--primary); }

/* ── 14. Accessibility: visible keyboard focus ──────────────────────── */
.btn:focus-visible,
.textbtn:focus-visible,
.iconbtn:focus-visible,
.tactile:focus-visible,
.fab:focus-visible,
.bottom-nav__item:focus-visible,
.menu__item:focus-visible,
.menu__trigger:focus-visible,
.appbar__rename:focus-visible,
.chart-chooser__item:focus-visible,
.source-chooser__item:focus-visible,
.tracker-project__chart:focus-visible,
.settings-advanced__head:focus-visible,
.card.clickable:focus-visible,
.field__input:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ── 15. Accessibility: honour reduced-motion ───────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }
  /* Progress + loading feedback stays legible: keep them moving. */
  .spinner {
    animation-duration: 1.4s !important;
    animation-iteration-count: infinite !important;
  }
  .progress__fill::after {
    animation-duration: 3s !important;
    animation-iteration-count: infinite !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
 * TOUCH / DEVICE LAYER — mobile-first ergonomics
 *
 * Kept in one place so the rules are easy to audit. Everything here is
 * additive: on a desktop with a mouse the app renders exactly as before.
 * ===================================================================== */

/* Tapping app chrome should not start a text selection or pop the iOS
   "Look Up / Copy" callout. Scoped to touch-only devices so desktop keeps
   normal text selection. Fields always keep selectable text. */
@media (hover: none) {
  button,
  a,
  [role='button'],
  label,
  .appbar__title,
  .bottom-nav__item,
  .card {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
}

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

/* Inner scrollers must not hand the scroll off to the page behind them. */
.dialog,
.sheet,
.menu__popup,
.egrid__area,
.panzoom {
  overscroll-behavior: contain;
}

/* Touch-only devices: a "hover" state that is set by a tap sticks forever
   and fights with the real selection state, so neutralise hover styling. */
@media (hover: none) {
  .card.clickable:hover,
  .card[onclick]:hover,
  .card.chart-tile:hover,
  .card.tracker-tile:hover,
  .card.swatch-entry:hover,
  .card.project-card:hover,
  .card.tracker-project:hover,
  .card.empty-card:hover {
    transform: none;
    box-shadow: none;
    border-color: var(--outline-variant);
  }

  .ecell:hover {
    box-shadow: none;
  }

  .assign-tile:hover,
  .pswatch--tap:hover,
  .partner__frame:hover,
  .fab:hover,
  .iconbtn:hover:not(:disabled) {
    transform: none;
  }

  .tactile:hover:not(:active):not(:disabled) {
    transform: none;
    box-shadow: 0 4px 0 rgba(0, 0, 0, 0.28);
  }

  .btn--filled:hover:not(:disabled) {
    box-shadow: none;
  }

  .tracker-project__chart:hover,
  .menu__item:hover:not(:disabled),
  .chart-chooser__item:hover,
  .source-chooser__item:hover,
  .appbar__rename:hover,
  .textbtn:hover {
    background: transparent;
  }

  /* The rename affordance is hover-revealed on desktop; on touch it needs to
     be a real, comfortably sized tap target instead. */
  .appbar__rename {
    padding: 6px;
    margin: -6px;
  }
}

/* Coarse pointers (finger) get >=44px hit areas on the small controls. */
@media (pointer: coarse) {
  .textbtn {
    min-height: 44px;
    padding: 10px 12px;
  }

  .menu__item,
  .chart-chooser__item,
  .source-chooser__item,
  .tracker-project__chart,
  .settings-advanced__head {
    min-height: 44px;
  }

  .swatch-entry,
  .chart-tile {
    min-height: 56px;
  }

  .bottom-nav__item {
    min-width: 44px;
  }

  /* Drag targets: a 12px hue strip is hard to grab with a thumb. */
  .picker__hue {
    height: 20px;
  }

  .crop-handle {
    width: 26px;
    height: 26px;
  }

  .crop-handle--tl {
    left: -13px;
    top: -13px;
  }

  .crop-handle--tr {
    right: -13px;
    top: -13px;
  }

  .crop-handle--bl {
    left: -13px;
    bottom: -13px;
  }

  .crop-handle--br {
    right: -13px;
    bottom: -13px;
  }
}

/* Very small phones (iPhone SE, older Android): tighten the generous type
   scale so nothing overflows the 320-360px viewport. */
@media (max-width: 360px) {
  .section-title {
    font-size: 22px;
  }

  .empty-state__title {
    font-size: 22px;
  }

  .list-pad {
    padding-left: calc(14px + var(--safe-left));
    padding-right: calc(14px + var(--safe-right));
  }

  .editor-actions,
  .editor-info,
  .editor-selbar {
    padding-left: 10px;
    padding-right: 10px;
    gap: 6px;
  }
}

/* Landscape phones: the app bar is the only chrome worth keeping tight. */
@media (max-height: 460px) and (orientation: landscape) {
  .appbar {
    min-height: 48px;
  }

  .bottom-nav__inner {
    height: 52px;
  }

  .list-pad {
    padding-bottom: calc(84px + var(--safe-bottom));
  }
}
