/* ==========================================================================
   Tasazo — dark glassmorphism with alarm-meter accents.

   Mobile-first: every base rule targets a phone held in one hand, and the two
   `min-width` queries below only ever add. The app's whole use case is someone
   standing at a till, so the narrow screen is the design, not the fallback.

   Organised as: tokens, reset, backdrop, layout, components, utilities.
   ========================================================================== */

/* --------------------------------------------------------- Design tokens */
/*
 * Light is the base; dark arrives through the system preference or an explicit
 * choice. Only the palette changes between them — every rule below this block
 * is written once and reads its colours from these variables.
 */
:root {
  --bg: #eaeef6;
  /* Opaque, not translucent: on a light ground a 72 % white panel over a near
     white page is invisible. The glass belongs to the dark theme alone. */
  --surface: #ffffff;
  --surface-blur: none;
  --border: #dde2ec;
  --border-strong: #c3cad9;
  --well: #f3f5fa;
  --wash: #eef1f7;
  --glow: rgba(20, 22, 42, 0.12);

  --text: #0f1222;
  --text-muted: #4b5170;
  --text-faint: #6b7191;

  /* Darkened against a light ground: every value below clears 4.5:1 on white,
     which the neon set used by the dark theme does not. */
  --merchant: #046a86;
  --official: #0a7346;
  --parallel: #95530a;
  --euro: #5b32b8;

  --good: #0a7346;
  --warn: #7d5806;
  --bad: #95530a;
  --critical: #c00537;
  --bargain: #046a86;

  --backdrop-warm: rgba(192, 5, 55, 0.14);
  --backdrop-cool: rgba(4, 106, 134, 0.12);
  --grid-line: rgba(20, 22, 42, 0.045);
  --panel-shadow: 0 1px 2px rgba(16, 20, 40, 0.05), 0 12px 28px -18px rgba(16, 20, 40, 0.45);
  --toast-bg: #ffffff;
  --needle: #0f1222;
  --needle-hub: #ffffff;
  --input-bg: #ffffff;
  --input-bg-focus: #ffffff;
  --track-bg: #e4e8f1;

  --radius-lg: 20px;
  --radius-md: 15px;
  --radius-sm: 12px;

  /* Smallest comfortable target for a thumb. */
  --tap: 44px;

  --font-sans: 'Outfit', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'Space Grotesk', ui-monospace, 'Cascadia Mono', Consolas, monospace;
}

/*
 * The dark palette applies only on request. Light is the default whatever the
 * device prefers, so there is no prefers-color-scheme branch here.
 */
:root[data-theme='dark'] {
  --bg: #08090a;
  --surface: rgba(255, 255, 255, 0.05);
  --surface-blur: blur(18px) saturate(140%);
  --border: rgba(255, 255, 255, 0.1);
  --border-strong: rgba(255, 255, 255, 0.18);
  --well: rgba(0, 0, 0, 0.4);
  --wash: rgba(255, 255, 255, 0.055);
  --glow: rgba(255, 255, 255, 0.16);

  --text: #f2f3f4;
  --text-muted: #9a9ca1;
  --text-faint: #67696f;

  --merchant: #00e5ff;
  --official: #22e08a;
  --parallel: #ff9f1c;
  --euro: #b18cff;

  --good: #22e08a;
  --warn: #ffd23f;
  --bad: #ff9f1c;
  --critical: #ff2e63;
  --bargain: #00e5ff;

  /* Neutral glows: any colour here casts a tint over the whole page. */
  --backdrop-warm: rgba(255, 255, 255, 0.07);
  --backdrop-cool: rgba(255, 255, 255, 0.055);
  --grid-line: rgba(255, 255, 255, 0.035);
  --panel-shadow: 0 20px 50px -25px #000;
  --toast-bg: rgba(18, 18, 19, 0.94);
  --needle: #ffffff;
  --needle-hub: #0d0d0e;
  --input-bg: rgba(0, 0, 0, 0.35);
  --input-bg-focus: rgba(0, 0, 0, 0.5);
  --track-bg: rgba(0, 0, 0, 0.5);
}

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

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

body {
  position: relative;
  min-height: 100dvh;
  /* Bottom padding clears the home indicator on a notched phone. */
  padding: 20px 16px calc(40px + env(safe-area-inset-bottom));
  overflow-x: hidden;
  font-family: var(--font-sans);
  color: var(--text);
  background: var(--bg);
}

button {
  font: inherit;
  cursor: pointer;
}

a {
  color: inherit;
}

/* ------------------------------------------------------------- Backdrop */
/*
 * Two blurred blobs. Kept modest on a phone — a 60vmax blur is a real cost on
 * a mid-range device — and allowed to grow once there is a screen to fill.
 */
body::before,
body::after {
  content: '';
  position: fixed;
  z-index: -2;
  width: 70vmax;
  height: 70vmax;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.42;
  pointer-events: none;
}

body::before {
  inset: -35vmax auto auto -30vmax;
  background: radial-gradient(circle, var(--backdrop-warm), transparent 65%);
}

body::after {
  inset: auto -30vmax -35vmax auto;
  background: radial-gradient(circle, var(--backdrop-cool), transparent 65%);
}

.backdrop-grid {
  position: fixed;
  inset: 0;
  z-index: -1;
  opacity: 0.35;
  pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 38px 38px;
  -webkit-mask-image: radial-gradient(ellipse at 50% 15%, #000 20%, transparent 75%);
  mask-image: radial-gradient(ellipse at 50% 15%, #000 20%, transparent 75%);
}

/* --------------------------------------------------------------- Layout */
/*
 * One narrow column at every width. The app asks for a single number and
 * answers it, so there is nothing to put beside anything else — and a measure
 * this wide reads the same on a phone as on a desktop.
 */
.layout {
  max-width: 620px;
  margin: 0 auto;
}

.layout > * + * {
  margin-top: 14px;
}

/* ------------------------------------------------------------- Masthead */
.masthead {
  position: relative;
  margin-bottom: 22px;
  text-align: center;
}

.theme-toggle {
  position: absolute;
  top: -4px;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
  font-size: 1.1rem;
  line-height: 1;
  transition: border-color 0.18s, transform 0.18s;
}

.theme-toggle:hover {
  border-color: var(--border-strong);
  transform: scale(1.06);
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--merchant);
  outline-offset: 2px;
}

.brand-mark {
  display: block;
  width: 48px;
  height: 48px;
  margin: 0 auto 10px;
  border-radius: 12px;
  box-shadow: 0 8px 20px -10px rgba(10, 127, 156, 0.7);
}

.masthead h1 {
  margin: 0 0 6px;
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  background: linear-gradient(100deg, var(--text) 10%, var(--critical) 45%, var(--merchant) 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.tagline {
  max-width: 44ch;
  margin: 0 auto;
  color: var(--text-muted);
  font-size: 0.92rem;
  font-weight: 400;
  line-height: 1.5;
}

.accent-merchant { color: var(--merchant); }
.accent-official { color: var(--official); }
.accent-parallel { color: var(--parallel); }
.accent-euro { color: var(--euro); }

/* --------------------------------------------------------------- Panels */
.panel {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
  box-shadow: var(--panel-shadow), inset 0 1px 0 var(--wash);
}

.panel-head {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.panel-title {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 14px;
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

.panel-head .panel-title {
  margin-bottom: 0;
}

/* ----------------------------------------------------------- Disclosure */
/*
 * Native <details>, so the groups work with JavaScript off, answer to the
 * keyboard and turn up in the browser's find-in-page.
 */
.disclosure {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
  overflow: hidden;
}

.disclosure-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  padding: 12px 16px;
  color: var(--text-muted);
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  transition: color 0.18s, background 0.18s;
}

.disclosure-summary::-webkit-details-marker {
  display: none;
}

.disclosure-summary:hover {
  background: var(--well);
  color: var(--text);
}

.disclosure-summary:focus-visible {
  outline: 2px solid var(--merchant);
  outline-offset: -2px;
}

.disclosure-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.disclosure-text small {
  color: var(--text-faint);
  font-size: 0.74rem;
  font-weight: 400;
}

.disclosure-summary:hover .disclosure-text small {
  color: var(--text-muted);
}

.disclosure-icon {
  color: var(--merchant);
  font-size: 0.8rem;
  transition: transform 0.2s ease;
}

.disclosure[open] .disclosure-summary {
  border-bottom: 1px solid var(--border);
  color: var(--text);
}

.disclosure[open] .disclosure-icon {
  transform: rotate(90deg);
}

.disclosure-body {
  padding: 16px;
}

/* --------------------------------------------------------- Status strip */
.status {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  background: var(--well);
  transition: border-color 0.3s, background 0.3s;
}

.status-pip {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
}

.status-body {
  flex: 1 1 60%;
  min-width: 0;
  font-size: 0.78rem;
  line-height: 1.45;
}

.status-detail {
  display: block;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  /* Long rate strings must wrap rather than push the layout sideways. */
  overflow-wrap: anywhere;
}

.status.is-live { border-color: color-mix(in srgb, var(--good) 40%, transparent); background: color-mix(in srgb, var(--good) 8%, transparent); }
.status.is-live .status-pip {
  background: var(--good);
  box-shadow: 0 0 10px var(--good);
  animation: heartbeat 2.4s infinite;
}

.status.is-stale { border-color: color-mix(in srgb, var(--warn) 40%, transparent); background: color-mix(in srgb, var(--warn) 8%, transparent); }
.status.is-stale .status-pip { background: var(--warn); box-shadow: 0 0 10px var(--warn); }

.status.is-offline { border-color: color-mix(in srgb, var(--critical) 40%, transparent); background: color-mix(in srgb, var(--critical) 8%, transparent); }
.status.is-offline .status-pip { background: var(--critical); box-shadow: 0 0 10px var(--critical); }

.status.is-loading .spinner {
  display: inline-block;
  animation: spin 0.8s linear infinite;
}

@keyframes heartbeat {
  50% { opacity: 0.25; transform: scale(0.7); }
}

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

/* --------------------------------------------------------------- Fields */
.field + .field,
.field-pair + .field,
.field + .field-pair {
  margin-top: 14px;
}

/* Stacked by default; side by side only once there is room for both labels. */
.field-pair {
  display: grid;
  gap: 12px;
}

.field-pair .field + .field {
  margin-top: 0;
}

/* One source, both its currencies, one auto/manual switch over the pair. */
.rate-group {
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--well);
}

.rate-group + .rate-group {
  margin-top: 12px;
}

.rate-group-head {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 0 10px;
}

.input-rate {
  padding-left: 52px;
  font-size: 0.95rem;
}

.field-label {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 7px;
  color: var(--text-muted);
  font-size: 0.82rem;
}

.field-name {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-size: 0.86rem;
  font-weight: 600;
}

.chip {
  padding: 3px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 0.66rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.chip-merchant { color: var(--merchant); border-color: color-mix(in srgb, var(--merchant) 40%, transparent); background: color-mix(in srgb, var(--merchant) 9%, transparent); }
.chip-official { color: var(--official); border-color: color-mix(in srgb, var(--official) 40%, transparent); background: color-mix(in srgb, var(--official) 9%, transparent); }
.chip-parallel { color: var(--parallel); border-color: color-mix(in srgb, var(--parallel) 40%, transparent); background: color-mix(in srgb, var(--parallel) 9%, transparent); }

.input-shell {
  position: relative;
  display: flex;
  align-items: center;
}

.input-prefix {
  position: absolute;
  left: 14px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 500;
  pointer-events: none;
}

.input-prefix-lead {
  font-size: 1.1rem;
}

.input {
  width: 100%;
  min-height: var(--tap);
  padding: 13px 14px 13px 46px;
  border: 1px solid var(--border-strong);
  border-radius: 13px;
  outline: none;
  background: var(--input-bg);
  color: var(--text);
  font-family: var(--font-mono);
  /*
   * Never below 16px: iOS Safari zooms the viewport on focus for anything
   * smaller, and the page never zooms back out on blur.
   */
  font-size: 1rem;
  font-weight: 500;
  transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
}

.input::placeholder {
  color: var(--text-faint);
  font-weight: 400;
}

.input:focus {
  border-color: var(--merchant);
  background: var(--input-bg-focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--merchant) 18%, transparent);
}

.input-lead {
  padding: 16px 14px 16px 52px;
  font-size: 1.7rem;
  letter-spacing: -0.02em;
}

.input.is-auto {
  border-color: color-mix(in srgb, var(--official) 30%, transparent);
  background: color-mix(in srgb, var(--official) 6%, transparent);
}

/* Worked out from a price, not typed: flagged like an automatic rate is. */
.input.is-derived {
  border-color: color-mix(in srgb, var(--merchant) 45%, transparent);
  background: color-mix(in srgb, var(--merchant) 7%, transparent);
}

.input.is-invalid {
  border-color: var(--critical);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--critical) 18%, transparent);
}

.input.just-updated {
  animation: pulse-ring 0.9s ease;
}

@keyframes pulse-ring {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--official) 45%, transparent); }
  60% { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: none; }
}

/* ------------------------------------------------------------- Controls */
.mode-toggle {
  position: relative;
  padding: 5px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--wash);
  color: var(--text-muted);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: filter 0.18s, color 0.18s, border-color 0.18s;
}

/* Grows the hit area to thumb size without inflating the pill itself. */
.mode-toggle::after {
  content: '';
  position: absolute;
  inset: -11px -8px;
}

.mode-toggle.is-auto {
  border-color: color-mix(in srgb, var(--official) 45%, transparent);
  background: color-mix(in srgb, var(--official) 10%, transparent);
  color: var(--official);
}

.mode-toggle:hover {
  filter: brightness(1.25);
}

.button-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: var(--tap);
  padding: 10px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--wash);
  color: var(--text-muted);
  font-size: 0.82rem;
  font-weight: 600;
  transition: color 0.18s, border-color 0.18s, background 0.18s;
}

.button-ghost:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--critical) 50%, transparent);
  background: color-mix(in srgb, var(--critical) 10%, transparent);
  color: var(--critical);
}

.button-compact {
  padding: 8px 14px;
  font-size: 0.78rem;
}

.status .button-compact:hover:not(:disabled) {
  border-color: var(--border-strong);
  background: var(--wash);
  color: var(--text);
}

.button-ghost:disabled {
  opacity: 0.5;
  cursor: wait;
}

.segmented {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--track-bg);
}

.segmented button {
  min-height: 38px;
  padding: 8px 10px;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--text-muted);
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  transition: color 0.18s, background 0.18s;
}

.segmented button:hover {
  color: var(--text);
}

.segmented button.is-selected {
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--border-strong);
  color: var(--text);
}

.toggle-row {
  display: grid;
  gap: 4px;
  margin-top: 14px;
}

.toggle {
  display: flex;
  gap: 10px;
  align-items: center;
  min-height: var(--tap);
  color: var(--text-muted);
  font-size: 0.82rem;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

.toggle input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
}

.toggle-track {
  position: relative;
  flex: none;
  width: 40px;
  height: 22px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--track-bg);
  transition: background 0.2s, border-color 0.2s;
}

.toggle-track::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-muted);
  transition: transform 0.2s, background 0.2s;
}

.toggle input:checked + .toggle-track {
  border-color: color-mix(in srgb, var(--good) 60%, transparent);
  background: color-mix(in srgb, var(--good) 15%, transparent);
}

.toggle input:checked + .toggle-track::after {
  transform: translateX(18px);
  background: var(--good);
  box-shadow: 0 0 10px var(--good);
}

.toggle input:focus-visible + .toggle-track {
  outline: 2px solid var(--merchant);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- Gauge */
.meter {
  margin-top: 18px;
  text-align: center;
}

.gauge-frame {
  max-width: 320px;
  margin: 0 auto;
}

.gauge {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.gauge-scale {
  fill: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 11px;
}

.gauge-track {
  stroke: var(--track-bg);
}

.gauge-ticks {
  stroke: color-mix(in srgb, var(--text-muted) 65%, transparent);
}

.gauge-needle line {
  stroke: var(--needle);
}

.gauge-needle circle {
  fill: var(--needle-hub);
  stroke: var(--needle);
}

.gauge-needle {
  transform-origin: 150px 150px;
  transition: transform 0.7s cubic-bezier(0.34, 1.36, 0.5, 1);
}

/*
 * Below the dial, not inside it. Pulled up over the arc the figure landed on
 * the needle's hub, which reads as a rendering fault rather than a design.
 */
.reading {
  margin-top: 2px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 2.8rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  transition: color 0.4s, text-shadow 0.4s;
}

.reading small {
  margin-left: 2px;
  font-size: 0.42em;
  font-weight: 500;
  opacity: 0.6;
}

.reading-label {
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.verdict {
  margin-top: 16px;
  padding: 14px 15px;
  border: 1px solid var(--border-strong);
  border-radius: 16px;
  background: var(--well);
  transition: border-color 0.4s, background 0.4s;
}

.verdict-emoji {
  font-size: 1.8rem;
  line-height: 1;
}

.verdict-title {
  margin-top: 6px;
  font-size: 1rem;
  font-weight: 600;
}

.verdict-detail {
  margin-top: 5px;
  color: var(--text-muted);
  font-size: 0.82rem;
  font-weight: 400;
  line-height: 1.5;
}

.verdict.is-alarming {
  animation: shudder 0.5s;
}

@keyframes shudder {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}

/* -------------------------------------------------------------- Results */
.results {
  display: grid;
  gap: 10px;
}

/*
 * Stacked on a phone: the amounts are the point, and squeezing them beside a
 * label costs the digits their size. They move alongside at 420px.
 */
.result {
  display: grid;
  gap: 10px;
  padding: 13px 14px;
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  background: var(--well);
  transition: background 0.25s;
}

.result-name {
  font-size: 0.88rem;
  font-weight: 600;
}

.result-rate {
  margin-top: 4px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.result-amounts {
  display: flex;
  gap: 12px;
  align-items: baseline;
}

.result-usd {
  font-family: var(--font-mono);
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.result-eur {
  color: var(--euro);
  font-family: var(--font-mono);
  font-size: 1.05rem;
  font-weight: 500;
}

.result[data-rate='merchant'] { border-left-color: var(--merchant); }
.result[data-rate='merchant'] .result-usd { color: var(--merchant); }
.result[data-rate='official'] { border-left-color: var(--official); }
.result[data-rate='official'] .result-usd { color: var(--official); }
.result[data-rate='parallel'] { border-left-color: var(--parallel); }
.result[data-rate='parallel'] .result-usd { color: var(--parallel); }

.empty {
  padding: 22px 10px;
  color: var(--text-muted);
  font-size: 0.88rem;
  font-weight: 400;
  text-align: center;
}

/* ----------------------------------------------------------- Comparison */
.comparison {
  display: grid;
  gap: 10px;
  margin-top: 18px;
}

.comparison-card {
  padding: 13px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--well);
}

.comparison-head {
  margin-bottom: 8px;
  color: var(--text-muted);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.comparison-usd {
  font-family: var(--font-mono);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.comparison-eur {
  margin-top: 3px;
  color: var(--euro);
  font-family: var(--font-mono);
  font-size: 0.92rem;
  font-weight: 500;
}

.comparison-percent {
  margin-top: 6px;
  font-size: 0.8rem;
  font-weight: 600;
}

.meter-bar {
  height: 5px;
  margin-top: 10px;
  border-radius: 999px;
  background: var(--track-bg);
  overflow: hidden;
}

.meter-bar span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  transition: width 0.6s ease, background 0.4s;
}

/* ----------------------------------------------------------------- Tone */
/*
 * The single place a tone becomes a colour. JavaScript only ever writes a tone
 * name — `data-tone="critical"` — which is why a second palette costs nothing
 * beyond the variables at the top of this file.
 */
[data-tone='good'] { --tone: var(--good); }
[data-tone='warn'] { --tone: var(--warn); }
[data-tone='bad'] { --tone: var(--bad); }
[data-tone='critical'] { --tone: var(--critical); }
[data-tone='bargain'] { --tone: var(--bargain); }

.gauge-zone {
  stroke: var(--tone);
}

.reading[data-tone] {
  color: var(--tone);
  text-shadow: 0 0 34px color-mix(in srgb, var(--tone) 40%, transparent);
}

.verdict[data-tone] {
  border-color: color-mix(in srgb, var(--tone) 40%, transparent);
  background: color-mix(in srgb, var(--tone) 8%, transparent);
}

.meter-bar span[data-tone] {
  background: var(--tone);
  box-shadow: 0 0 12px color-mix(in srgb, var(--tone) 70%, transparent);
}

/* --------------------------------------------------------------- Motion */
/*
 * Movement here is meant to explain, not decorate: things that arrive slide in
 * from where they came from, things that respond move under the finger, and
 * the gauge draws itself so the scale reads as a scale. All of it is switched
 * off wholesale by prefers-reduced-motion at the end of this file.
 */

/* Panels arrive in reading order on load. */
.layout > .panel,
.layout > .disclosure,
.layout > .masthead {
  animation: rise-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.layout > *:nth-child(1) { animation-delay: 0.02s; }
.layout > *:nth-child(2) { animation-delay: 0.08s; }
.layout > *:nth-child(3) { animation-delay: 0.14s; }
.layout > *:nth-child(4) { animation-delay: 0.2s; }
.layout > *:nth-child(5) { animation-delay: 0.26s; }

@keyframes rise-in {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}

/* A conversion that was not there a moment ago slides in from the left edge. */
.result.is-entering {
  animation: result-in 0.42s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

@keyframes result-in {
  from { opacity: 0; transform: translateX(-14px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

/* Disclosure contents unfold rather than appearing whole. */
.disclosure[open] .disclosure-body {
  animation: unfold 0.36s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes unfold {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: none; }
}

/*
 * The gauge draws its own scale when the group opens, left to right, so the
 * bands read as a progression instead of a static ring.
 */
.disclosure[open] .gauge-zone {
  /* Longer than the full semicircle (πr ≈ 377) so no band shows a gap. */
  stroke-dasharray: 400;
  animation: sweep 0.9s ease-out backwards;
}

.disclosure[open] .gauge-zone:nth-child(1) { animation-delay: 0.05s; }
.disclosure[open] .gauge-zone:nth-child(2) { animation-delay: 0.14s; }
.disclosure[open] .gauge-zone:nth-child(3) { animation-delay: 0.23s; }
.disclosure[open] .gauge-zone:nth-child(4) { animation-delay: 0.32s; }

@keyframes sweep {
  from { stroke-dashoffset: 400; opacity: 0; }
  to { stroke-dashoffset: 0; opacity: 0.85; }
}

.disclosure[open] .gauge-needle {
  animation: needle-settle 1.1s cubic-bezier(0.34, 1.36, 0.5, 1) backwards;
}

@keyframes needle-settle {
  from { opacity: 0; transform: rotate(-14deg); }
  40% { opacity: 1; }
  to { opacity: 1; }
}

/* Anything pressable gives under the finger. */
.button-ghost:active:not(:disabled),
.mode-toggle:active,
.segmented button:active,
.theme-toggle:active,
.disclosure-summary:active {
  transform: scale(0.96);
}

.theme-toggle:active {
  transform: scale(0.9) rotate(-12deg);
}

.button-ghost,
.mode-toggle,
.segmented button,
.disclosure-summary {
  transition: color 0.18s, border-color 0.18s, background 0.18s, transform 0.12s ease;
}

/* The amount field lifts as you use it — it is the one input that matters. */
.input-lead {
  transition: border-color 0.18s, box-shadow 0.25s, background 0.18s, transform 0.25s ease;
}

.input-lead:focus {
  transform: translateY(-2px);
}

/* The reading counts itself up rather than snapping between figures. */
.reading {
  transition: color 0.4s, text-shadow 0.4s, transform 0.35s cubic-bezier(0.34, 1.36, 0.5, 1);
}

.reading[data-tone] {
  animation: reading-pop 0.4s cubic-bezier(0.34, 1.36, 0.5, 1);
}

@keyframes reading-pop {
  from { transform: scale(0.92); }
  to { transform: scale(1); }
}

/* The live pip breathes while the rates are current. */
.status.is-live {
  animation: settle 0.5s ease;
}

@keyframes settle {
  from { opacity: 0.4; }
  to { opacity: 1; }
}

/* ------------------------------------------------------------ Utilities */
.tone-good { color: var(--good); }
.tone-warn { color: var(--warn); }
.tone-bad { color: var(--bad); }
.tone-critical { color: var(--critical); }
.tone-bargain { color: var(--bargain); }

.note {
  margin-top: 10px;
  color: var(--text-muted);
  font-size: 0.76rem;
  font-weight: 400;
  line-height: 1.55;
}

.note b {
  color: var(--text);
  font-weight: 600;
}

/*
 * Loud enough to catch an eye that is already reading the figure it doubts,
 * quiet enough not to read as an error: nothing here is wrong, something here
 * is suspicious.
 */
.warning {
  /*
   * Not a flex row: flex would make the emoji, the sentence and the closing
   * "?" three separate items and space them apart, breaking the punctuation
   * off the word before it. Absolute icon, hanging indent, ordinary text flow.
   */
  position: relative;
  margin-top: 10px;
  padding: 9px 11px 9px 34px;
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--warn) 9%, transparent);
  color: var(--text);
  font-size: 0.78rem;
  line-height: 1.5;
}

.warning::before {
  content: '💡';
  position: absolute;
  top: 9px;
  left: 11px;
}

.warning b {
  color: var(--warn);
  font-weight: 700;
  white-space: nowrap;
}

.warning[hidden] {
  display: none;
}

.colophon {
  margin-top: 26px;
  color: var(--text-faint);
  font-size: 0.74rem;
  font-weight: 400;
  line-height: 1.7;
  text-align: center;
}

.colophon b {
  color: var(--text-muted);
  font-weight: 600;
}

.colophon a {
  color: var(--text-faint);
  text-decoration: none;
  border-bottom: 1px dotted currentcolor;
}

.colophon a:hover {
  border-bottom-style: solid;
}

/* The byline closes the page, so it is set apart from the small print above
   it rather than reading as one more line of it. */
.signature {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
}

.signature a {
  color: var(--text);
  font-weight: 600;
  letter-spacing: 0;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--merchant) 45%, transparent);
  transition: color 0.18s, border-color 0.18s;
}

.signature a:hover {
  color: var(--merchant);
  border-bottom-color: var(--merchant);
}

/* ---------------------------------------------------------------- Toast */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(20px + env(safe-area-inset-bottom));
  z-index: 99;
  max-width: calc(100vw - 32px);
  padding: 12px 18px;
  border: 1px solid var(--border-strong);
  border-radius: 13px;
  background: var(--toast-bg);
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
  font-size: 0.84rem;
  font-weight: 500;
  text-align: center;
  opacity: 0;
  transform: translate(-50%, 80px);
  pointer-events: none;
  transition: opacity 0.32s cubic-bezier(0.2, 1.2, 0.4, 1),
              transform 0.32s cubic-bezier(0.2, 1.2, 0.4, 1);
}

.toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ==========================================================================
   Enhancements. Everything above is the phone; these only add.
   ========================================================================== */

/* Wide enough for a label and its figures to share a line. */
@media (min-width: 420px) {
  .result {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
  }

  .result:hover {
    background: var(--wash);
    transform: translateX(2px);
  }

  .result-amounts {
    display: block;
    text-align: right;
    white-space: nowrap;
  }

  .result-eur {
    margin-top: 3px;
  }

  .field-pair {
    grid-template-columns: 1fr 1fr;
  }

  .comparison {
    grid-template-columns: 1fr 1fr;
  }

  .toggle-row {
    grid-template-columns: repeat(2, auto);
    justify-content: space-between;
  }
}

/* Comfortable on a laptop: more air, a bigger title, a showier backdrop. */
@media (min-width: 680px) {
  body {
    padding: 36px 24px 60px;
  }

  body::before,
  body::after {
    width: 60vmax;
    height: 60vmax;
    filter: blur(90px);
    opacity: 0.5;
  }

  body::before {
    inset: -25vmax auto auto -15vmax;
    animation: drift-warm 18s ease-in-out infinite alternate;
  }

  body::after {
    inset: auto -15vmax -25vmax auto;
    animation: drift-cool 22s ease-in-out infinite alternate;
  }

  .backdrop-grid {
    background-size: 46px 46px;
  }

  .layout > * + * {
    margin-top: 18px;
  }

  .masthead {
    margin-bottom: 32px;
  }

  .masthead h1 {
    font-size: 3.6rem;
  }

  .tagline {
    font-size: 1.02rem;
  }

  .panel,
  .disclosure-body {
    padding: 22px;
  }

  .disclosure-summary {
    padding: 16px 22px;
  }

  .input-lead {
    font-size: 2rem;
  }

  .reading {
    font-size: 3.4rem;
  }

  .gauge-frame {
    max-width: 340px;
  }
}

@keyframes drift-warm {
  to { transform: translate3d(8vw, 6vh, 0) scale(1.15); }
}

@keyframes drift-cool {
  to { transform: translate3d(-8vw, -5vh, 0) scale(1.2); }
}

/* --------------------------------------------------------- Preferences */
@media (prefers-reduced-motion: reduce) {
  body::before,
  body::after {
    animation: none;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
