/* ============================================================
   Subtraction Tracker — stylesheet

   Apple-style typographic minimalism, scaled up for low vision.
   Sizes are in rem and the root is enlarged, so everything scales
   together AND still responds to the iPhone's own Text Size setting.
   ============================================================ */

html {
  /* Global scale lever: 1rem = 20px rather than the 16px default. */
  font-size: 132%;
  -webkit-text-size-adjust: 100%;
}

:root,
[data-theme="light"] {
  --bg:              #F5F5F7;
  --surface:         #FFFFFF;
  --surface-veil:    rgba(255, 255, 255, 0.86);
  --text:            #1D1D1F;
  --text-dim:        #5E5E63;
  --accent:          #0071E3;
  --on-accent:       #FFFFFF;
  --neutral:         #1F7A46;
  --close:           #9A5B00;
  --success:         #0A6B31;
  --over:            #C9000F;
  --danger:          #C9000F;
  --on-danger:       #FFFFFF;
  --line:            rgba(0, 0, 0, 0.10);
  --press:           rgba(0, 0, 0, 0.06);
  --scrim:           rgba(0, 0, 0, 0.34);
  --lift:            0 1px 2px rgba(0, 0, 0, 0.06);
  --lift-lg:         0 10px 30px rgba(0, 0, 0, 0.16);
}

[data-theme="dark"] {
  --bg:              #000000;
  --surface:         #1C1C1E;
  --surface-veil:    rgba(28, 28, 30, 0.86);
  --text:            #F5F5F7;
  --text-dim:        #A1A1A6;
  --accent:          #0A84FF;
  --on-accent:       #FFFFFF;
  --neutral:         #5BD98A;
  --close:           #FFB340;
  --success:         #32D74B;
  --over:            #FF453A;
  --danger:          #FF453A;
  --on-danger:       #FFFFFF;
  --line:            rgba(255, 255, 255, 0.16);
  --press:           rgba(255, 255, 255, 0.10);
  --scrim:           rgba(0, 0, 0, 0.6);
  --lift:            0 1px 2px rgba(0, 0, 0, 0.4);
  --lift-lg:         0 10px 30px rgba(0, 0, 0, 0.6);
}

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

html, body { height: 100%; }

body {
  /* Fixed so the page itself can never scroll when the keyboard
     opens — only the inner scroller moves. */
  position: fixed;
  inset: 0;
  margin: 0;
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 1.2rem;
  -webkit-font-smoothing: antialiased;
  transition: background-color 200ms ease-out;
}

button, input {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  border: none;
  background: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;   /* no tap/double-tap-zoom ambiguity */
}

.is-hidden { display: none !important; }

.icon {
  width: 26px;
  height: 26px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-lg { width: 32px; height: 32px; }

:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

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

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 60px;
  padding: 0 12px;
  margin: 0 -12px;
  border-radius: 16px;
  font-size: 1.35rem;
  font-weight: 500;
  transition: background-color 150ms ease-out, transform 150ms ease-out;
}

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  transition: background-color 150ms ease-out, transform 150ms ease-out;
}
.btn-icon--filled { background: var(--surface); }

.btn-text {
  min-height: 54px;
  padding: 0 16px;
  border-radius: 16px;
  color: var(--accent);
  font-size: 1.4rem;
  font-weight: 600;
  transition: background-color 150ms ease-out, transform 150ms ease-out;
}
.btn-text--muted { color: var(--text-dim); }

.btn-primary {
  width: 100%;
  min-height: 66px;
  padding: 0 20px;
  border-radius: 18px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 1.4rem;
  font-weight: 700;
  transition: transform 150ms ease-out, filter 150ms ease-out;
}

.btn-danger {
  min-height: 60px;
  padding: 0 20px;
  border-radius: 16px;
  background: var(--danger);
  color: var(--on-danger);
  font-size: 1.25rem;
  font-weight: 700;
  transition: transform 150ms ease-out;
}

.btn-danger-text {
  width: 100%;
  min-height: 62px;
  border-radius: 16px;
  color: var(--danger);
  font-size: 1.35rem;
  font-weight: 600;
  transition: background-color 150ms ease-out, transform 150ms ease-out;
}

.btn-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 66px;
  height: 66px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--lift);
  transition: transform 150ms ease-out;
}

button:active { transform: scale(0.96); }
.btn-ghost:active,
.btn-icon:active,
.btn-text:active,
.btn-danger-text:active { background-color: var(--press); }

/* ---------------------------------------------------- fields */

.field {
  width: 100%;
  min-width: 0;                /* stops intrinsic width forcing overflow */
  border: none;
  border-radius: 18px;
  background: var(--surface);
  padding: 16px 20px;
  font-variant-numeric: tabular-nums;
}
.field:focus { outline: 3px solid var(--accent); outline-offset: -3px; }

.field--price {
  min-height: 66px;
  font-size: 1.9rem;
  font-weight: 600;
}
.field--label {
  min-height: 64px;
  font-size: 1.35rem;
}

/* ============================================================ APP SHELL */

.app {
  /* --vh is kept in sync with visualViewport by app.js, so the layout
     resizes to the space above the keyboard instead of scrolling. */
  height: 100dvh;
  height: var(--vh, 100dvh);
  display: flex;
  flex-direction: column;
}

/* ---------------------------------------------------- header */

.header {
  flex: none;
  padding: max(env(safe-area-inset-top), 10px) 20px 2px;
}

.header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* Two separate targets: the clock opens History, the wordmark opens
   the website. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.brand-link {
  display: inline-flex;
  align-items: center;
  min-height: 60px;
  padding: 0 6px;
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  border-radius: 14px;
  -webkit-tap-highlight-color: transparent;
}
.brand-link:active { background: var(--press); }

/* ---------------------------------------------------- scroller */

.scroller {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  padding: 6px 20px 0;
}

.scroller-tail { height: 16px; }

.empty {
  margin: 0;
  padding: 18px 20px;
  text-align: center;
  font-size: 1.4rem;
  line-height: 1.5;
  color: var(--text-dim);
}

.empty-line { margin: 0; }

.credit {
  margin: 10px 0 0;
  text-align: center;
  font-size: 1rem;
  line-height: 1.4;
  color: var(--text-dim);
  opacity: 0.8;
}

.credit a,
.feedback a {
  color: var(--accent);
  text-decoration: none;
}

.feedback {
  margin: 6px 0 0;
  text-align: center;
  font-size: 1rem;
}
.feedback a {
  display: inline-block;
  padding: 8px 14px;      /* comfortable tap target on its own line */
}

/* ---------------------------------------------------- target cards */

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

/* A target card is a swipeable row: dragging left reveals an action
   (Remove when there are several targets, Reset when there's only one).
   Same mechanics as the item rows. */
.tier {
  position: relative;
  overflow: hidden;
  border-radius: 18px;
}

.tier-action {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 18px;
  background: var(--danger);
  color: var(--on-danger);
  font-size: 1.15rem;
  font-weight: 700;
}

.tier-face {
  position: relative;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;          /* long values drop the state to line 2
                               rather than clipping; short values,
                               the common case, stay on one line */
  column-gap: 12px;
  row-gap: 2px;
  width: 100%;
  text-align: left;
  padding: 14px 16px;
  border-radius: 18px;
  background: var(--surface);
  box-shadow: var(--lift);
  transform: translateX(0);
  transition: transform 200ms ease-out, box-shadow 150ms ease-out;
  touch-action: pan-y;
}
.tier-face.is-selected { box-shadow: 0 0 0 3px var(--accent); }

.tier-name {
  flex: none;
  font-size: 1.15rem;
  color: var(--text-dim);
}

.tier-value {
  flex: none;
  font-size: 1.9rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tier-value.is-unset { color: var(--text-dim); font-weight: 500; }

/* Sits in what used to be empty space to the right of the value, so the
   whole card is one line instead of three. */
.tier-state {
  margin-left: auto;
  flex: 0 1 auto;
  min-width: 0;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--neutral);
  white-space: nowrap;
}

.row-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin: 10px 0 12px;
}

/* ---------------------------------------------------- item rows */

.item-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.item {
  position: relative;
  overflow: hidden;
  border-radius: 18px;
  margin-bottom: 8px;
}

.item-delete {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 18px;
  background: var(--danger);
  color: var(--on-danger);
  font-size: 1.15rem;
  font-weight: 700;
}

.item-face {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 64px;
  padding: 12px 20px;
  border-radius: 18px;
  background: var(--surface);
  transform: translateX(0);
  transition: transform 200ms ease-out;
  touch-action: pan-y;
}

.item-price {
  display: block;
  font-size: 1.75rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.item-label {
  display: block;
  margin-top: 2px;
  font-size: 1.2rem;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@keyframes pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.02); }
  100% { transform: scale(1); }
}
.item.is-new .item-face { animation: pop 300ms ease-out; }

/* ============================================================ BOTTOM BAR */

.bottombar {
  flex: none;
  padding: 10px 20px max(env(safe-area-inset-bottom), 12px);
  background: var(--surface-veil);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  border-top: 1px solid var(--line);
  transition: background-color 200ms ease-out;
}

.result {
  display: block;
  width: 100%;
  padding: 2px 12px 6px;
  margin: -4px -12px 0;
  border-radius: 22px;
  text-align: center;
  transition: background-color 150ms ease-out, transform 150ms ease-out;
}
.result:active { background-color: var(--press); }

/* Sits under the big number; the item count now sits above it. */
.result-status {
  display: block;
  margin-top: 2px;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--neutral);
  transition: color 220ms ease-out;
}

/* With no target set the prompt stands alone, so it carries the weight
   the number normally would. */
.result-status.is-prompt {
  margin: 18px 0;
  font-size: 2.4rem;
  color: var(--accent);   /* tappable, so same accent as the other links */
}

.result-number {
  display: block;
  margin: 0 0 2px;
  font-size: clamp(3.7rem, 16vw, 5rem);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  transition: color 220ms ease-out;
}

.result-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 2px;
  font-size: 1.25rem;
  color: var(--text-dim);
}
.result-meta .dot { opacity: 0.5; }

/* Shared state colours. Each is paired with its own word — "to go",
   "nearly there", "reached", "exceeded" — so meaning never rests on
   colour alone. Green for "to go" reads as "keep going"; "reached" uses
   a deeper/brighter green, and the words tell the two apart. */
.is-neutral { color: var(--neutral); }
.is-close   { color: var(--close); }
.is-hit     { color: var(--success); }
.is-over    { color: var(--over); }

@keyframes celebrate {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
.result-number.just-hit { animation: celebrate 400ms ease-out; }

.bottombar-divider {
  height: 1px;
  margin: 8px 0 10px;
  background: var(--line);
}

.entry-label-row { margin-bottom: 10px; }

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

/* ============================================================ UNDO ROW

   Rendered in the list where the deleted item was, deliberately NOT as
   a bar floating over the entry field — so the price input stays clear
   and the next item can be entered while undo is still offered. */

.undo-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 64px;
  padding: 10px 12px 10px 20px;
  border-radius: 18px;
  background: var(--surface);
  border: 2px dashed var(--line);
}

.undo-text {
  font-size: 1.3rem;
  color: var(--text-dim);
}

.undo-action {
  flex: none;
  min-height: 56px;
  padding: 0 20px;
  border-radius: 14px;
  color: var(--accent);
  font-size: 1.35rem;
  font-weight: 700;
}
.undo-action:active { background: var(--press); }

/* ============================================================ SCREENS */

.screen {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--vh, 100dvh);
  z-index: 40;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

.screen-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: max(env(safe-area-inset-top), 14px) 20px 6px;
}

.screen-title {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
}

.screen-head-pad { width: 92px; }

.screen-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px 20px 20px;
}

.screen-foot {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 20px max(env(safe-area-inset-bottom), 18px);
}

/* history list */

.history-list { list-style: none; margin: 0; padding: 0; }

.trip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  min-height: 72px;
  padding: 18px;
  margin-bottom: 12px;
  border-radius: 18px;
  background: var(--surface);
  text-align: left;
  transition: transform 150ms ease-out;
}

.trip-name { display: block; font-size: 1.4rem; font-weight: 600; }
.trip-meta { display: block; margin-top: 3px; font-size: 1.15rem; color: var(--text-dim); }
.trip-total {
  flex: none;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* trip detail */

.detail-head {
  margin: 18px 0 10px;
  font-size: 1.05rem;
  color: var(--text-dim);
}

.detail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 64px;
  padding: 16px 18px;
  margin-bottom: 10px;
  border-radius: 16px;
  background: var(--surface);
  font-size: 1.35rem;
}
.detail-row-state { font-size: 1.1rem; font-weight: 700; text-align: right; }

/* ============================================================ SHEETS */

.sheet {
  position: fixed;
  top: var(--vv-top, 0px);
  left: 0;
  right: 0;
  /* Height must follow the VISUAL viewport, not `inset: 0`. iOS lays
     fixed elements out against the layout viewport, which does not
     shrink for the keyboard — so `inset: 0` parks the panel behind it. */
  height: var(--vh, 100dvh);
  z-index: 60;
  display: flex;
  align-items: flex-end;
  /* A dismissed panel is translated below the container; clipping
     guarantees it can never peek out under a shrunken viewport. */
  overflow: hidden;
}
.sheet.is-hidden {
  display: flex !important;
  pointer-events: none;
}
.sheet.is-hidden .sheet-scrim { opacity: 0; }
.sheet.is-hidden .sheet-panel { transform: translateY(100%); }

.sheet-scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  opacity: 1;
  transition: opacity 200ms ease-out;
}

.sheet-panel {
  position: relative;
  width: 100%;
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 10px 20px max(env(safe-area-inset-bottom), 20px);
  border-radius: 26px 26px 0 0;
  background: var(--bg);
  transform: translateY(0);
  transition: transform 220ms ease-out;
}

.sheet-grip {
  display: block;
  width: 44px;
  height: 6px;
  margin: 4px auto 16px;
  border-radius: 3px;
  background: var(--line);
}

.sheet-label {
  display: block;
  margin: 14px 0 8px;
  font-size: 1.25rem;
  color: var(--text-dim);
}

.sheet-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 24px;
}

/* ============================================================ DIALOG */

.dialog {
  position: fixed;
  top: var(--vv-top, 0px);
  left: 0;
  right: 0;
  height: var(--vh, 100dvh);
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.dialog.is-hidden { display: flex !important; pointer-events: none; }
.dialog.is-hidden .dialog-scrim { opacity: 0; }
.dialog.is-hidden .dialog-panel { opacity: 0; transform: scale(0.94); }

.dialog-scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  opacity: 1;
  transition: opacity 200ms ease-out;
}

.dialog-panel {
  position: relative;
  width: 100%;
  max-width: 380px;
  padding: 26px 22px;
  border-radius: 22px;
  background: var(--surface);
  box-shadow: var(--lift-lg);
  opacity: 1;
  transform: scale(1);
  transition: opacity 200ms ease-out, transform 200ms ease-out;
}

.dialog-text {
  margin: 2px 0 22px;
  text-align: center;
  font-size: 1.4rem;
  font-weight: 500;
  line-height: 1.4;
}

.dialog-actions {
  display: flex;
  gap: 12px;
}

/* The dialog lays its buttons out in a row, so the primary button
   must not stretch to full width the way it does in sheets. */
.btn-primary.btn-inline {
  width: auto;
  min-height: 60px;
  font-size: 1.25rem;
}
.dialog-actions > * { flex: 1; }

/* ============================================================ */

/* ============================================================ COMPACT

   Applied by app.js when the visible viewport is short — in practice,
   whenever the keyboard is up. Everything tightens just enough that no
   control is pushed off-screen. Text stays large; only the slack goes.
   The full-size layout returns the moment the keyboard closes. */

.is-compact .header { padding-top: max(env(safe-area-inset-top), 8px); }
.is-compact .header-row { min-height: 0; }
.is-compact .btn-ghost,
.is-compact .btn-icon { min-height: 52px; height: 52px; }

.is-compact .result { padding: 2px 12px 6px; margin-bottom: 0; }
.is-compact .result-status { font-size: 1.1rem; }
.is-compact .result-status .icon { width: 20px; height: 20px; }
.is-compact .result-number { font-size: 2.7rem; margin: 0 0 2px; }
.is-compact .result-meta { font-size: 1rem; }
.is-compact .bottombar { padding-top: 8px; }
.is-compact .bottombar-divider { margin: 6px 0 10px; }

.is-compact .field--price { min-height: 60px; font-size: 1.5rem; padding: 12px 18px; }
.is-compact .field--label { min-height: 56px; padding: 12px 18px; }
.is-compact .btn-add { width: 60px; height: 60px; }

.is-compact .sheet-panel { padding-top: 6px; }
.is-compact .sheet-grip { margin: 2px auto 10px; }
.is-compact .sheet-label { margin: 8px 0 6px; font-size: 1.05rem; }
.is-compact .sheet-actions { margin-top: 14px; gap: 10px; flex-direction: row; }
.is-compact .sheet-actions > * { flex: 1; width: auto; }
.is-compact .btn-primary { min-height: 58px; }
.is-compact .btn-danger-text { min-height: 58px; font-size: 1.1rem; }

/* Freshly-opened overlays ignore input for a moment, so the click the
   browser synthesises after touchend can't dismiss them or trigger a
   button underneath the finger. Scoped to the scrim and the action
   buttons only — the input stays tappable, so the keyboard is always
   reachable by hand if it ever fails to appear on its own. */
.sheet.is-arming .sheet-scrim,
.sheet.is-arming .sheet-actions,
.dialog.is-arming .dialog-scrim,
.dialog.is-arming .dialog-actions { pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
