/* ==========================================================================
   Inocreal design system
   --------------------------------------------------------------------------
   Written as tokens first, components second. Nothing below references a raw
   colour: every value comes from a custom property, so the light and dark
   themes are the same stylesheet with one block of overrides.

   Theme resolution, in order of precedence:
     1. [data-theme="light"|"dark"] on <html>  (explicit user choice)
     2. prefers-color-scheme                    (system setting)
     3. light                                   (default)
   ========================================================================== */

/* --------------------------------------------------------------- 1. fonts */

@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('fonts/outfit-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('fonts/outfit-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* -------------------------------------------------------------- 2. tokens */

:root {
  /* Type: a 1.200 minor-third ramp, fluid between 360px and 1240px viewports.
     Minor third rather than a larger ratio because this UI is dense with
     short labels, and a wide ramp makes those fight each other. */
  --font-sans: 'Outfit', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: clamp(1.0625rem, 1rem + 0.3vw, 1.125rem);
  --text-xl: clamp(1.25rem, 1.15rem + 0.5vw, 1.375rem);
  --text-2xl: clamp(1.5rem, 1.3rem + 1vw, 1.875rem);
  --text-3xl: clamp(1.875rem, 1.5rem + 1.9vw, 2.75rem);
  --text-4xl: clamp(2.25rem, 1.6rem + 3.2vw, 4rem);

  --leading-tight: 1.15;
  --leading-snug: 1.35;
  --leading-normal: 1.6;

  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.06em;

  /* Space: 4px base. Every margin, padding and gap in this file uses one of
     these, which is what keeps vertical rhythm consistent across sections. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 20px;
  --radius-full: 999px;

  --container: 78rem;
  --container-narrow: 40rem;

  /* Layout rhythm. These are the only two values the page frame uses, so the
     whole document tightens or loosens from here. They are fluid rather than
     stepped: the old flat 4rem/6rem block padding was two thirds of a phone
     screen between one section and the next, and left a 20rem gutter either
     side of a 1152px container on a wide monitor. */
  --gutter: clamp(1rem, 3.5vw, 2rem);
  --section-y: clamp(2.25rem, 4.5vw, 3.75rem);
  --hero-y: clamp(2.5rem, 5.5vw, 4.25rem);

  --duration-fast: 120ms;
  --duration-base: 220ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.5, 1);

  --border: 1px solid var(--line);

  /* --- Light theme (default) ---
     A warm off-white ground rather than pure white: it lowers glare and makes
     the white cards read as raised without needing heavy shadows. */
  --bg: #f7f6f3;
  --bg-subtle: #efede8;
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --line: #e3e0d9;
  --line-strong: #cec9be;

  --ink: #1a1917;
  --ink-muted: #5c584f;
  --ink-subtle: #6f6a60;

  --accent: #0d7d78;
  --accent-hover: #0a625e;
  --accent-ink: #ffffff;
  --accent-wash: #d9efee;

  --lost: #a15c00;
  --lost-wash: #fdf0dc;
  --found: #10695a;
  --found-wash: #d8efe9;

  --danger: #b3261e;
  --danger-wash: #fbe6e4;
  --success: #10695a;

  --focus: #0d7d78;

  --shadow-sm: 0 1px 2px rgb(26 25 23 / 0.05);
  --shadow-md: 0 2px 4px rgb(26 25 23 / 0.04), 0 8px 20px rgb(26 25 23 / 0.06);
  --shadow-lg: 0 4px 8px rgb(26 25 23 / 0.05), 0 20px 48px rgb(26 25 23 / 0.12);

  color-scheme: light;
}

/* --- Dark theme ---
   Not the light palette inverted. Surfaces lift with lightness rather than
   shadow (shadows are near-invisible on dark), the accent is desaturated up
   to stay legible on a dark ground, and the ink never reaches pure white,
   which halates against dark backgrounds. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #12120f;
    --bg-subtle: #191917;
    --surface: #1c1c19;
    --surface-raised: #232320;
    --line: #302f2b;
    --line-strong: #45443e;

    --ink: #f0eee9;
    --ink-muted: #b2ada2;
    --ink-subtle: #98938a;

    --accent: #4ecdc4;
    --accent-hover: #6fd9d1;
    --accent-ink: #06201f;
    --accent-wash: #17322f;

    --lost: #e6a44c;
    --lost-wash: #33260f;
    --found: #4ecdc4;
    --found-wash: #14312e;

    --danger: #f08b83;
    --danger-wash: #3a1b18;
    --success: #4ecdc4;

    --focus: #4ecdc4;

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow-md: 0 2px 4px rgb(0 0 0 / 0.3), 0 8px 20px rgb(0 0 0 / 0.4);
    --shadow-lg: 0 4px 8px rgb(0 0 0 / 0.3), 0 20px 48px rgb(0 0 0 / 0.55);

    color-scheme: dark;
  }
}

:root[data-theme='dark'] {
  --bg: #12120f;
  --bg-subtle: #191917;
  --surface: #1c1c19;
  --surface-raised: #232320;
  --line: #302f2b;
  --line-strong: #45443e;

  --ink: #f0eee9;
  --ink-muted: #b2ada2;
  --ink-subtle: #98938a;

  --accent: #4ecdc4;
  --accent-hover: #6fd9d1;
  --accent-ink: #06201f;
  --accent-wash: #17322f;

  --lost: #e6a44c;
  --lost-wash: #33260f;
  --found: #4ecdc4;
  --found-wash: #14312e;

  --danger: #f08b83;
  --danger-wash: #3a1b18;
  --success: #4ecdc4;

  --focus: #4ecdc4;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-md: 0 2px 4px rgb(0 0 0 / 0.3), 0 8px 20px rgb(0 0 0 / 0.4);
  --shadow-lg: 0 4px 8px rgb(0 0 0 / 0.3), 0 20px 48px rgb(0 0 0 / 0.55);

  color-scheme: dark;
}

/* ---------------------------------------------------------------- 3. base */

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--space-8);
}

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

h1,
h2,
h3,
h4 {
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  font-weight: 600;
  text-wrap: balance;
}

h1 {
  font-size: var(--text-4xl);
}

h2 {
  font-size: var(--text-3xl);
}

h3 {
  font-size: var(--text-xl);
}

p {
  text-wrap: pretty;
}

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

a {
  color: var(--accent);
  text-underline-offset: 0.2em;
}

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

/* One focus treatment everywhere. The previous stylesheet set outline:none on
   every field with nothing in its place, which made keyboard use invisible. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

:focus:not(:focus-visible) {
  outline: none;
}

::selection {
  background: var(--accent-wash);
  color: var(--ink);
}

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

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: 200;
  padding: var(--space-3) var(--space-4);
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: var(--radius-sm);
  font-weight: 600;
  transform: translateY(-200%);
  transition: transform var(--duration-base) var(--ease-out);
}

.skip-link:focus {
  transform: translateY(0);
}

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* -------------------------------------------------------------- 4. header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px) saturate(1.4);
  border-bottom: var(--border);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 4rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 600;
  font-size: var(--text-lg);
  letter-spacing: var(--tracking-tight);
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
}

.brand img {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
}

.brand sup {
  font-size: 0.5em;
  font-weight: 500;
  color: var(--ink-subtle);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--ink-muted);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: 500;
  transition: color var(--duration-fast), background var(--duration-fast);
}

.site-nav a:hover {
  color: var(--ink);
  background: var(--bg-subtle);
}

@media (max-width: 30rem) {
  .site-nav {
    display: none;
  }
}

.theme-toggle {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--ink-muted);
  cursor: pointer;
  transition: color var(--duration-fast), border-color var(--duration-fast);
}

.theme-toggle:hover {
  color: var(--ink);
  border-color: var(--line-strong);
}

/* Each glyph is shown only in the theme it switches away from. */
.theme-toggle .icon-moon {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .icon-sun {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .icon-moon {
  display: block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .theme-toggle .icon-sun {
    display: none;
  }

  :root:not([data-theme='light']) .theme-toggle .icon-moon {
    display: block;
  }
}

/* ---------------------------------------------------------------- 5. hero */

.hero {
  position: relative;
  padding-block: var(--hero-y) var(--section-y);
  overflow: hidden;
}

/* Do NOT cap the width here. This element also carries .container, which
   sets margin-inline:auto with a 72rem cap; narrowing it again re-centres
   the whole block, so the hero sat 192px inboard of the header, the cards,
   the form and the footer. Constrain the children instead, and the hero's
   left edge lines up with every other section. */
.hero__inner > * {
  max-width: 52rem;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  margin-bottom: var(--space-5);
  border: var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.eyebrow::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--found);
}

.hero h1 {
  margin-bottom: var(--space-5);
}

.hero h1 em {
  font-style: normal;
  color: var(--accent);
}

.hero__lead {
  font-size: var(--text-lg);
  color: var(--ink-muted);
  max-width: 38rem;
  margin-bottom: var(--space-5);
}

/* The search field is the hero's primary control: most visitors arrive to
   look for something, not to post. It also fills the space the old
   two-button row left empty on wide screens. */
.hero__search {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 38rem;
  padding: var(--space-2);
  padding-left: calc(var(--space-4) * 2 + 0.5rem);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-md);
  transition: border-color var(--duration-fast), box-shadow var(--duration-fast);
}

.hero__search:focus-within {
  border-color: var(--accent);
  box-shadow: var(--shadow-md), 0 0 0 3px var(--accent-wash);
}

.hero__search > .icon {
  position: absolute;
  left: var(--space-4);
  width: 1.25rem;
  height: 1.25rem;
  color: var(--ink-subtle);
  pointer-events: none;
}

.hero__search input {
  flex: 1;
  min-width: 0;
  padding: var(--space-2) 0;
  background: none;
  border: 0;
  font-size: var(--text-base);
}

.hero__search input:focus {
  outline: none;
  box-shadow: none;
}

/* Browse / Search / Report. Three taps that cover everything the site does,
   above the fold on a phone, so nothing needs to be discovered by scrolling. */
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

@media (max-width: 26rem) {
  .hero__actions .btn {
    flex: 1 1 100%;
  }
}

@media (max-width: 30rem) {
  .hero__search {
    flex-wrap: wrap;
    padding-left: var(--space-2);
    border-radius: var(--radius-lg);
  }

  .hero__search > .icon {
    display: none;
  }

  .hero__search input {
    padding-inline: var(--space-3);
  }

  .hero__search .btn {
    width: 100%;
  }
}

/* ----------------------------------------------------------- how it works */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: var(--space-4);
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: step;
}

.step-card {
  padding: var(--space-5);
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius-lg);
}

.step-card__num {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  margin-bottom: var(--space-3);
  border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 600;
}

.step-card h2 {
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}

.step-card p {
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

/* ---------------------------------------------------------------- filters */

.feed-filters {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

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

.chip {
  min-height: 40px;
  padding: var(--space-2) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-full);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast),
    border-color var(--duration-fast);
}

.chip:hover {
  color: var(--ink);
  border-color: var(--ink-subtle);
}

.chip.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.result-count {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* A quiet field of dots behind the hero. Decorative only, hidden from AT,
   and masked so it fades out rather than ending on a hard edge. */
.hero__pattern {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(circle at 1px 1px, var(--line-strong) 1px, transparent 0);
  background-size: 28px 28px;
  mask-image: radial-gradient(ellipse 70% 60% at 70% 30%, #000 0%, transparent 75%);
  opacity: 0.7;
  pointer-events: none;
}

/* ------------------------------------------------------------- 6. buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast), color var(--duration-fast),
    transform var(--duration-fast) var(--ease-out);
}

.btn:active {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}

.btn--primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.btn--primary:hover:not(:disabled) {
  background: var(--accent-hover);
}

.btn--secondary {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--line-strong);
}

.btn--secondary:hover:not(:disabled) {
  background: var(--bg-subtle);
  border-color: var(--ink-subtle);
}

.btn--ghost {
  background: transparent;
  color: var(--ink-muted);
}

.btn--ghost:hover:not(:disabled) {
  background: var(--bg-subtle);
  color: var(--ink);
}

.btn--sm {
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-xs);
}

.btn--block {
  width: 100%;
}

/* ------------------------------------------------------------ 7. sections */

.section {
  padding-block: var(--section-y);
}

.section--alt {
  background: var(--bg-subtle);
  border-block: var(--border);
}

.section__head {
  max-width: 44rem;
  margin-bottom: var(--space-5);
}

.section__head p {
  margin-top: var(--space-3);
  color: var(--ink-muted);
  font-size: var(--text-lg);
}

/* ---------------------------------------------------------------- 8. form */

.form-card {
  max-width: var(--container-narrow);
  padding: clamp(var(--space-4), 3vw, var(--space-6));
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

@media (max-width: 30rem) {
  .form-card {
    padding: var(--space-5) var(--space-4);
  }
}

/* Fieldsets group the form into what / where / who so it reads as three
   short questions instead of one column of nine inputs. */
.fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-5);
}

.fieldset:last-of-type {
  margin-bottom: var(--space-4);
}

.fieldset__legend {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-4);
  border-bottom: var(--border);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-subtle);
}

.fieldset__legend .step {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent);
  font-size: 11px;
}

.field {
  margin-bottom: var(--space-4);
}

.field:last-child {
  margin-bottom: 0;
}

.field > label,
.field-label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink);
}

.field-row {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 34rem) {
  .field-row {
    grid-template-columns: 1fr 1fr;
  }
}

input[type='text'],
input[type='date'],
input[type='time'],
input[type='email'],
textarea,
select {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  transition: border-color var(--duration-fast), box-shadow var(--duration-fast);
}

textarea {
  resize: vertical;
  min-height: 5.5rem;
  line-height: var(--leading-normal);
}

input:hover:not(:disabled),
textarea:hover,
select:hover {
  border-color: var(--ink-subtle);
}

input:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}

::placeholder {
  color: var(--ink-subtle);
  opacity: 1;
}

select {
  appearance: none;
  padding-right: var(--space-7);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236f6a60' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
}

:root[data-theme='dark'] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2398938a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}

.hint {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
  color: var(--ink-muted);
}

.hint--privacy {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3);
  margin-top: var(--space-3);
  background: var(--accent-wash);
  border-radius: var(--radius-sm);
  color: var(--ink-muted);
}

.hint--privacy .icon {
  color: var(--accent);
  width: 1rem;
  height: 1rem;
  margin-top: 2px;
}

/* Errors are announced, not just coloured: the message carries the text and
   the field gets aria-invalid, so colour is never the only signal. */
.error-message {
  display: none;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--danger);
}

.field.is-invalid .error-message {
  display: block;
}

.field.is-invalid input,
.field.is-invalid textarea,
.field.is-invalid select,
.field.is-invalid .file-drop {
  border-color: var(--danger);
}

.field.is-invalid input:focus,
.field.is-invalid textarea:focus {
  box-shadow: 0 0 0 3px var(--danger-wash);
}

/* Segmented LOST / FOUND control, replacing a <select> of two options. */
.segmented {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
  padding: var(--space-1);
  background: var(--bg-subtle);
  border: var(--border);
  border-radius: var(--radius-md);
}

.segmented input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.segmented label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast),
    box-shadow var(--duration-fast);
}

.segmented input:checked + label {
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

.segmented input:focus-visible + label {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* File upload */
.file-drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 9rem;
  padding: var(--space-5);
  background: var(--bg);
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--radius-md);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--duration-fast), background var(--duration-fast);
}

.file-drop:hover {
  border-color: var(--accent);
  background: var(--accent-wash);
}

.file-drop input[type='file'] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

.file-drop .icon {
  width: 1.75rem;
  height: 1.75rem;
  color: var(--ink-subtle);
}

.file-drop__label {
  font-size: var(--text-sm);
  font-weight: 500;
}

.file-drop__meta {
  font-size: var(--text-xs);
  color: var(--ink-muted);
}

.file-drop.has-file {
  border-style: solid;
  border-color: var(--accent);
  background: var(--accent-wash);
}

.file-drop__preview {
  display: none;
  width: 100%;
  max-height: 12rem;
  object-fit: contain;
  border-radius: var(--radius-sm);
}

.file-drop.has-file .file-drop__preview {
  display: block;
}

.file-drop.has-file .icon {
  display: none;
}

/* Map picker */
.map-picker {
  height: 13rem;
  margin-top: var(--space-3);
  border: var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  z-index: 0;
}

.map-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

/* --------------------------------------------------------------- 9. feed */

.feed-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.search {
  position: relative;
  flex: 1 1 18rem;
}

.search .icon {
  position: absolute;
  left: var(--space-4);
  top: 50%;
  translate: 0 -50%;
  width: 1.125rem;
  height: 1.125rem;
  color: var(--ink-subtle);
  pointer-events: none;
}

.search input {
  padding-left: calc(var(--space-4) * 2 + 1.125rem);
  border-radius: var(--radius-full);
  background: var(--surface);
}

.items-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-4);
}

.item-card {
  display: flex;
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--duration-base) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out),
    border-color var(--duration-base);
}

.item-card:hover {
  transform: translateY(-3px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}

/* The entire card is the control, so the click target matches what the eye
   reads as clickable. */
.item-card__button {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
}

.item-card__button:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

.item-card__marks {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.item-card__cta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 600;
}

.item-card__cta .icon {
  width: 1rem;
  height: 1rem;
  transition: translate var(--duration-fast) var(--ease-out);
}

.item-card:hover .item-card__cta .icon {
  translate: 3px 0;
}

.item-card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--bg-subtle);
}

.item-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.item-card__placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  height: 100%;
  color: var(--ink-subtle);
  font-size: var(--text-xs);
}

.item-card__placeholder .icon {
  width: 1.5rem;
  height: 1.5rem;
}

.item-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  flex: 1;
}

.item-card__title {
  font-size: var(--text-lg);
  font-weight: 600;
  overflow-wrap: anywhere;
}

.item-card__meta {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  overflow-wrap: anywhere;
}

.item-card__meta .icon {
  width: 1rem;
  height: 1rem;
  margin-top: 3px;
  color: var(--ink-subtle);
}

.item-card__actions {
  margin-top: auto;
  padding-top: var(--space-3);
}

/* The tag sits on the image, so it needs its own opaque ground rather than
   inheriting the card surface. */
.tag {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  backdrop-filter: blur(8px);
}

.tag--LOST {
  background: var(--lost-wash);
  color: var(--lost);
}

.tag--FOUND {
  background: var(--found-wash);
  color: var(--found);
}

.feed-state {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--ink-muted);
}

.feed-state .icon {
  width: 2rem;
  height: 2rem;
  color: var(--ink-subtle);
}

/* Skeletons hold the grid's shape during the first load so the page does not
   jump when items arrive. */
.skeleton-card {
  height: 20rem;
  border-radius: var(--radius-lg);
  border: var(--border);
  background: linear-gradient(
    100deg,
    var(--surface) 30%,
    var(--bg-subtle) 50%,
    var(--surface) 70%
  );
  background-size: 220% 100%;
  animation: shimmer 1.4s infinite linear;
}

@keyframes shimmer {
  to {
    background-position-x: -220%;
  }
}

.items-map {
  height: 30rem;
  border: var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  z-index: 0;
}

/* --------------------------------------------------------------- 10. modal */

.modal {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: rgb(0 0 0 / 0.45);
  backdrop-filter: blur(4px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--duration-base) var(--ease-out),
    visibility var(--duration-base);
}

.modal.is-open {
  opacity: 1;
  visibility: visible;
}

.modal__panel {
  width: min(34rem, 100%);
  max-height: min(85dvh, 48rem);
  overflow-y: auto;
  padding: var(--space-6);
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  translate: 0 12px;
  scale: 0.98;
  transition: translate var(--duration-base) var(--ease-spring),
    scale var(--duration-base) var(--ease-spring);
}

.modal.is-open .modal__panel {
  translate: 0 0;
  scale: 1;
}

@media (max-width: 30rem) {
  .modal__panel {
    padding: var(--space-5) var(--space-4);
  }
}

.modal__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.modal__head h2 {
  font-size: var(--text-xl);
  flex: 1;
}

.modal__close {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: none;
  border: 0;
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast);
}

.modal__close:hover {
  background: var(--line);
  color: var(--ink);
}

.modal__subject {
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--bg-subtle);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  overflow-wrap: anywhere;
}

.modal__subject strong {
  display: block;
  font-size: var(--text-base);
  color: var(--ink);
}

.modal__footer {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: var(--border);
  font-size: var(--text-xs);
  color: var(--ink-muted);
}

.modal__footer .icon {
  width: 1rem;
  height: 1rem;
  margin-top: 2px;
  flex: none;
}

.form-status {
  min-height: 1.25rem;
  margin-block: var(--space-3);
  font-size: var(--text-sm);
  font-weight: 500;
}

.form-status.is-error {
  color: var(--danger);
}

.form-status.is-success {
  color: var(--success);
}

.form-status.is-pending {
  color: var(--ink-muted);
}

/* ------------------------------------------------------- 11. notifications */

.toasts {
  position: fixed;
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(22rem, calc(100vw - var(--space-6)));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-raised);
  border: var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  font-size: var(--text-sm);
  pointer-events: auto;
  animation: toast-in var(--duration-base) var(--ease-spring);
}

.toast--success {
  border-left-color: var(--success);
}

.toast--error {
  border-left-color: var(--danger);
}

.toast .icon {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 1px;
}

.toast--success .icon {
  color: var(--success);
}

.toast--error .icon {
  color: var(--danger);
}

.toast.is-leaving {
  animation: toast-out var(--duration-base) var(--ease-out) forwards;
}

@keyframes toast-in {
  from {
    opacity: 0;
    translate: 0 12px;
  }
}

@keyframes toast-out {
  to {
    opacity: 0;
    translate: 0 8px;
  }
}

/* ------------------------------------------------------------- 12. footer */

.site-footer {
  padding-block: var(--space-6);
  margin-top: var(--section-y);
  background: var(--bg-subtle);
  border-top: var(--border);
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.site-footer a {
  color: var(--ink-muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--ink);
  text-decoration: underline;
}

/* ----------------------------------------------------------- 14. map skin */

/* Shared chrome first, then the provider-specific overrides. Both map
   providers get the same surface, the same popup and the same loading state,
   so swapping one for the other is invisible to the reader. */

.map-picker,
.items-map {
  position: relative;
  background: var(--bg-subtle);
}

/* Google Maps and Leaflet both need a beat to fetch their runtime. Without
   this the container is an empty bordered rectangle, which reads as broken
   rather than as loading - the single most common complaint about the old
   map. */
.map-picker.is-loading::after,
.items-map.is-loading::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    var(--bg-subtle) 30%,
    var(--surface) 50%,
    var(--bg-subtle) 70%
  );
  background-size: 220% 100%;
  animation: shimmer 1.4s infinite linear;
}

/* Shown in place of the map when no provider could be loaded at all. */
.map-fallback {
  display: grid;
  place-items: center;
  height: 100%;
  margin: 0;
  padding: var(--space-4);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

/* The popup body is one element built in script.js and handed to whichever
   provider is live, so it is styled once here rather than twice below. */
.map-popup {
  min-width: 12rem;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--ink);
}

.map-popup h3 {
  font-size: var(--text-base);
  margin-bottom: var(--space-2);
}

.map-popup .item-card__meta {
  margin-bottom: var(--space-1);
}

.popup-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

/* --- Leaflet --- */

.leaflet-container {
  font-family: var(--font-sans);
  background: var(--bg-subtle);
}

.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
  background: var(--surface-raised);
  color: var(--ink);
  box-shadow: var(--shadow-lg);
}

.leaflet-popup-content-wrapper {
  border-radius: var(--radius-md);
  border: var(--border);
}

.leaflet-popup-content {
  margin: var(--space-4);
}

/* --- Google Maps --- */

/* Google paints its own bubble. Only the inner surface and the tail are
   ours; the rest of the widget is left alone on purpose, because its
   internals are renamed between releases and over-styling them breaks
   silently on the next one. */
.gm-style .gm-style-iw-c {
  padding: 0;
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  box-shadow: var(--shadow-lg);
}

.gm-style .gm-style-iw-d {
  padding: var(--space-4);
  overflow: auto !important;
}

.gm-style .gm-style-iw-tc::after {
  background: var(--surface-raised);
}

/* Google's close button is a white-on-white <button> against our dark
   surface, so it is recoloured rather than hidden - it is the only way out
   of the bubble on a touch screen. */
.gm-style .gm-style-iw-c button[aria-label='Close'] span,
.gm-style .gm-ui-hover-effect > span {
  background-color: var(--ink-muted) !important;
}

.leaflet-control-zoom a,
.leaflet-control-attribution {
  background: var(--surface) !important;
  color: var(--ink-muted) !important;
  border-color: var(--line) !important;
}

.leaflet-control-attribution a {
  color: var(--accent) !important;
}

/* Dark mode has no dark tile server here, so the tiles are filtered instead.
   Cheap, and consistent with the rest of the surface. */
:root[data-theme='dark'] .leaflet-tile-pane {
  filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.9);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.9);
  }
}

/* --------------------------------------------------------------- 15. motion */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }

  .item-card:hover,
  .step-card:hover {
    transform: none;
  }

  .item-card__button:hover .item-card__media img {
    scale: 1;
  }

  .theme-toggle:hover .icon {
    rotate: 0deg;
    scale: 1;
  }

  /* Revealed content must never be left invisible when the observer's
     transition is suppressed. */
  .reveal {
    opacity: 1;
    translate: none;
  }
}

/* ------------------------------------------------------------- 16. prose */

/* Long-form pages (privacy, terms). Narrow measure, generous rhythm. */
.prose {
  max-width: 44rem;
  margin-inline: auto;
  padding-block: var(--space-8);
}

.prose > * + * {
  margin-top: var(--space-4);
}

.prose h1 {
  font-size: var(--text-3xl);
}

.prose h2 {
  font-size: var(--text-xl);
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: var(--border);
}

.prose h3 {
  font-size: var(--text-lg);
  margin-top: var(--space-5);
}

.prose ul {
  padding-left: var(--space-5);
}

.prose li + li {
  margin-top: var(--space-2);
}

.prose li::marker {
  color: var(--ink-subtle);
}

.prose .updated {
  font-size: var(--text-sm);
  color: var(--ink-subtle);
}

.prose .callout {
  padding: var(--space-4);
  background: var(--accent-wash);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--accent);
}


/* ---------------------------------------------------------- 17. item detail */

.modal__panel--wide {
  width: min(46rem, 100%);
  padding: 0;
  position: relative;
  overflow: hidden;
}

.modal__panel--wide .modal__close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 2;
  background: var(--surface-raised);
  border: var(--border);
}

.detail {
  display: grid;
  max-height: min(85dvh, 48rem);
  overflow-y: auto;
}

@media (min-width: 44rem) {
  .detail {
    grid-template-columns: 18rem 1fr;
  }
}

.detail__media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--bg-subtle);
  border-bottom: var(--border);
}

@media (min-width: 44rem) {
  .detail__media {
    aspect-ratio: auto;
    border-bottom: 0;
    border-right: var(--border);
  }
}

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

.detail__media .item-card__placeholder {
  min-height: 12rem;
}

.detail__body {
  padding: var(--space-5);
}

.detail__body .tag {
  position: static;
  margin-bottom: var(--space-3);
}

.detail__body h2 {
  font-size: var(--text-2xl);
  margin-bottom: var(--space-4);
  overflow-wrap: anywhere;
}

.detail__facts {
  margin-bottom: var(--space-5);
}

.detail__facts > div + div {
  margin-top: var(--space-4);
}

.detail__facts dt {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-subtle);
}

.detail__facts dt .icon {
  width: 0.9rem;
  height: 0.9rem;
}

.detail__facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}

#detail-marks {
  padding: var(--space-3);
  background: var(--bg-subtle);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  white-space: pre-wrap;
}

#claim-form {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: var(--border);
}

.install-btn {
  display: none;
}

@media (min-width: 30rem) {
  .install-btn:not([hidden]) {
    display: inline-flex;
  }
}


/* ========================================================================
   18. Motion
   Entrances are opt-in per element via .reveal, driven by an
   IntersectionObserver so nothing animates until it is actually on screen.
   Every rule here is switched off wholesale by the reduced-motion block at
   the end of this file.
   ======================================================================== */

/* Hero copy arrives on load, staggered top to bottom. No observer needed —
   it is above the fold by definition. */
/* Hero copy slides in on load, staggered top to bottom.

   Translate only, never opacity. Everything here is above the fold, so
   whichever element happens to be the Largest Contentful Paint (Lighthouse
   measures a 412px viewport, where it is the lead paragraph, not the
   heading) would not count as painted while it faded, and LCP would absorb
   the full animation delay plus duration. A translated element is painted.
   Fading is reserved for the decorative pattern, which can never be LCP. */
@media (prefers-reduced-motion: no-preference) {
  .hero__inner > * {
    animation: slide 620ms var(--ease-out) backwards;
  }

  .hero__inner > *:nth-child(2) { animation-delay: 50ms; }
  .hero__inner > *:nth-child(3) { animation-delay: 100ms; }
  .hero__inner > *:nth-child(4) { animation-delay: 150ms; }
  .hero__inner > *:nth-child(5) { animation-delay: 200ms; }

  .hero__pattern {
    animation: fade 1200ms var(--ease-out) backwards;
    animation-delay: 200ms;
  }
}

@keyframes slide {
  from {
    translate: 0 14px;
  }
}

@keyframes rise {
  from {
    opacity: 0;
    translate: 0 14px;
  }
}

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

/* Scroll reveal. The .reveal class is added by script.js only when an
   observer is available, so with JS off the content is simply visible. */
.reveal {
  opacity: 0;
  translate: 0 18px;
  transition: opacity 600ms var(--ease-out), translate 600ms var(--ease-out);
}

.reveal.is-visible {
  opacity: 1;
  translate: 0 0;
}

/* Grid children stagger by position rather than by index, so a filtered
   list re-staggers correctly without re-numbering anything. */
.items-grid .reveal:nth-child(3n + 2),
.steps .reveal:nth-child(3n + 2) {
  transition-delay: 70ms;
}

.items-grid .reveal:nth-child(3n + 3),
.steps .reveal:nth-child(3n + 3) {
  transition-delay: 140ms;
}

/* Theme swap. Colour transitions are enabled only while the class is on the
   root — a permanent transition would make the very first paint fade in,
   and would fight every hover state for the life of the page. */
:root.theme-transition,
:root.theme-transition *,
:root.theme-transition *::before,
:root.theme-transition *::after {
  transition: background-color 320ms var(--ease-out), border-color 320ms var(--ease-out),
    color 320ms var(--ease-out), fill 320ms var(--ease-out) !important;
  transition-delay: 0ms !important;
}

.theme-toggle .icon {
  transition: rotate var(--duration-base) var(--ease-spring),
    scale var(--duration-base) var(--ease-spring);
}

.theme-toggle:hover .icon {
  rotate: 25deg;
  scale: 1.08;
}

/* Card polish: the photo lifts slightly under the hover that already raises
   the card, so the two read as one movement. */
.item-card__media {
  overflow: hidden;
}

.item-card__media img {
  transition: scale 500ms var(--ease-out);
}

.item-card__button:hover .item-card__media img,
.item-card__button:focus-visible .item-card__media img {
  scale: 1.04;
}

.item-card__title {
  transition: color var(--duration-fast);
}

.item-card__button:hover .item-card__title {
  color: var(--accent);
}

.chip,
.btn,
.item-card,
.step-card {
  will-change: auto;
}

.step-card {
  transition: transform var(--duration-base) var(--ease-out),
    border-color var(--duration-base), box-shadow var(--duration-base);
}

.step-card:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-sm);
}

/* Toolbar controls settle rather than snap. */
.chip {
  transition: background var(--duration-fast) var(--ease-out),
    color var(--duration-fast), border-color var(--duration-fast),
    transform var(--duration-fast) var(--ease-out);
}

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

.skip-link {
  transition: color var(--duration-fast);
}
