/* css/tokens.css */
/* Generated by build.mjs from tokens.json. Do not edit. */

:root {
  --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  --bg: #dfded7;
  --surface: #d4d3cc;
  --fill-state: color-mix(in srgb, var(--text) 7%, transparent);
  --text: #2d2e2a;
  --text_body: #454641;
  --muted: #575752;
  --text_faint: #5a5a55;
  --border: #bab9b1;
  --link: var(--text);
  --ink: var(--text);
  --ink_contrast: var(--bg);
  --accent-amber: #7f4e02;
  --accent-teal: #1b635d;
  --accent-terracotta: #983b2b;
  --accent-olive: #49621a;
  --accent-indigo: #53548c;
  --accent-primary: var(--accent-indigo);
  --accent-secondary: var(--accent-teal);
  --accent-success: var(--accent-olive);
  --accent-insight: var(--accent-terracotta);
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-24: 6rem;
  --space-32: 8rem;
  --radius-control-xs: 6px;
  --radius-control-sm: 8px;
  --radius-control-md: 10px;
  --radius-control-lg: 12px;
  --radius-control-xl: 14px;
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 18px;
  --radius-pill: 999px;
  --control-xs: 24px;
  --control-sm: 32px;
  --control-md: 40px;
  --control-lg: 48px;
  --control-xl: 56px;
  --control-pad-xs: 8px;
  --control-pad-sm: 12px;
  --control-pad-md: 16px;
  --control-pad-lg: 20px;
  --control-pad-xl: 24px;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.10);
  --text-xs: 0.8125rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;
  --text-4xl: 2.875rem;
  --text-5xl: 3.75rem;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-black: 800;
  --leading-tight: 1.2;
  --leading-snug: 1.3;
  --leading-normal: 1.65;
  --leading-relaxed: 1.75;
  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.02em;
  --width-narrow: 468px;
  --width-reading: 700px;
  --width-content: 760px;
  --width-page: 1120px;
  --border-width: 1px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #212123;
    --surface: #303030;
    --text: #e2e2dd;
    --text_body: #d0d0d0;
    --muted: #adadad;
    --text_faint: #969696;
    --border: #444444;
    --accent-amber: #e0a451;
    --accent-teal: #5db0a7;
    --accent-terracotta: #db8670;
    --accent-olive: #9db85f;
    --accent-indigo: #979ace;
  }
}

[data-theme="dark"] {
  --bg: #212123;
  --surface: #303030;
  --text: #e2e2dd;
  --text_body: #d0d0d0;
  --muted: #adadad;
  --text_faint: #969696;
  --border: #444444;
  --accent-amber: #e0a451;
  --accent-teal: #5db0a7;
  --accent-terracotta: #db8670;
  --accent-olive: #9db85f;
  --accent-indigo: #979ace;
}

[data-theme="light"] {
  --bg: #dfded7;
  --surface: #d4d3cc;
  --text: #2d2e2a;
  --text_body: #454641;
  --muted: #575752;
  --text_faint: #5a5a55;
  --border: #bab9b1;
  --accent-amber: #7f4e02;
  --accent-teal: #1b635d;
  --accent-terracotta: #983b2b;
  --accent-olive: #49621a;
  --accent-indigo: #53548c;
}

/* css/reset.css */
/**
 * Modern CSS reset — small and opinionated.
 * Inspired by Andy Bell's reset (https://andy-bell.co.uk/a-modern-css-reset/).
 */

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

* {
  margin: 0;
  padding: 0;
}

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

@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;
  }
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

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

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

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

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  list-style: none;
}

p,
h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
  text-wrap: pretty;
}

h1, h2, h3, h4 {
  text-wrap: balance;
}

table {
  border-collapse: collapse;
}

hr {
  border: 0;
  height: var(--border-width, 1px);
  background: var(--border);
}

/* css/base.css */
/**
 * Element defaults. Wires tokens to native HTML elements.
 * After reset + tokens, this gives unstyled markup a good default look.
 */

html {
  background: var(--bg);
  color: var(--text);
}

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text);
  background: var(--bg);
}

/* ---- Headings: system serif ---- */

/* .h1–.h6 put a heading's look on any element, so the visual size can differ
   from the document level (a page's only heading styled as .h3, a <p> as .h5). */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--font-serif);
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
  margin: 0;                /* spacing handled by the section flow rhythm */
}

/* Type scale matched to the live enko.one (h1 36 / h2 28 / h3 24). */
h1, .h1 { font-size: 2.25rem; }  /* 36px */
h2, .h2 { font-size: 1.75rem; }  /* 28px */
h3, .h3 { font-size: 1.5rem; }   /* 24px */

h4, .h4 { font-size: var(--text-xl); }
h5, .h5 { font-size: var(--text-lg); }
h6, .h6 { font-size: var(--text-base); text-transform: uppercase; letter-spacing: var(--tracking-wide); }

/* ---- Hero treatment ---- */

.hero-heading {
  font-family: var(--font-serif);
  font-size: 2.5rem;        /* 40px — a touch above enko's 36px h1 for hero presence */
  font-weight: var(--font-weight-bold);
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
  max-width: 700px;
  margin: 0;
}

@media (max-width: 640px) {
  .hero-heading { font-size: 2rem; }
}

/* ---- Body text ---- */

p {
  margin: 0;
  color: var(--text_body);
}

small {
  font-size: var(--text-sm);
  color: var(--muted);
}

strong, b { font-weight: var(--font-weight-semibold); }
em, i    { font-style: italic; }

/* ---- Links ---- */

/* Neutral, editorial links: dark text + underline, distinguished by the
   underline rather than colour. Colour is reserved for the map/illustration. */
a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--border);
  text-underline-offset: 0.18em;
  transition: color 0.15s ease, text-decoration-color 0.15s ease;
}

a:hover { color: var(--text); text-decoration-color: currentColor; }

/* ---- Lists ---- */

ul.bullets,
ol.bullets {
  list-style: revert;
  padding-left: var(--space-6);
  margin-bottom: var(--space-6);
}

ul.bullets li,
ol.bullets li {
  margin-bottom: var(--space-2);
}

/* ---- Code ---- */

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--surface);
  padding: 0.1em 0.35em;
  border-radius: var(--radius-sm);
}

pre {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  background: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  overflow-x: auto;
}

pre code {
  background: transparent;
  padding: 0;
}

/* ---- Forms ---- */

fieldset {
  border: 0;
  min-width: 0;   /* a fieldset otherwise refuses to shrink below its content */
}

input, textarea, select {
  background: var(--bg);
  color: var(--text);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-sm);
}

/* One ring for everything focusable, <summary> and tabindex regions included.
   A real colour, never `outline: auto`, which draws the OS accent instead. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

/* ---- Utilities (a tiny set, not a full utility framework) ---- */

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

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

/* `caption` type style: helper text, meta, notes. */
.caption {
  font-size: var(--text-xs);
  color: var(--muted);
}

/* `eyebrow` type style: an uppercase mono kicker, e.g. a calendar's month. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-wide);
  line-height: var(--leading-snug);
  text-transform: uppercase;
  color: var(--muted);
}

/* The link look on anything, <button> included: `text` with a hairline
   underline that darkens on hover. Colour never marks a link. */
.link {
  padding: 0;
  font: inherit;
  color: var(--link);
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--border);
  text-underline-offset: 0.18em;
  transition: text-decoration-color 0.15s ease;
}

.link:hover { text-decoration-color: currentColor; }
.link:disabled { opacity: 0.45; cursor: not-allowed; }

/* One line, cut with an ellipsis; put the full text in title="". */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Mirrors a directional icon (back, next) in right-to-left languages. */
[dir="rtl"] .flip-rtl { transform: scaleX(-1); }

/* css/layout.css */
/**
 * Layout primitives. Single-column-first.
 *
 * Four widths:
 *   .page             — outer cap (width-page) — header, footer, body grid
 *   .content-column   — mixed content (width-content) — cards, image grids, tables
 *   .reading-column   — prose (width-reading) — long-form copy, FAQs, articles
 *   .narrow-column    — one task (width-narrow) — a form, a flow step, sign-in
 *
 * Three section sizes:
 *   .section          — default 96px block padding
 *   .section-tight    — 64px
 *   .section-loose    — 128px
 */

/* Gutter: space-4 on phones, space-6 from 768px. */
.page,
.narrow-column {
  margin-inline: auto;
  padding-inline: var(--space-4);
}

@media (min-width: 768px) {
  .page,
  .narrow-column { padding-inline: var(--space-6); }
}

.page { max-width: var(--width-page); }

/* Carries its own gutter, so it can stand alone as a phone screen's column. */
.narrow-column {
  width: 100%;
  max-width: var(--width-narrow);
}

.content-column {
  max-width: var(--width-content);
  margin-inline: auto;
}

.reading-column {
  max-width: var(--width-reading);
  margin-inline: auto;
}

/* Sizing matched to enko.one: ~80px between adjacent sections.
   Padding on both sides stacks, so 2.5rem each → ~80px gap. */
.section        { padding-block: 2.5rem; }
.section-tight  { padding-block: 1.5rem; }
.section-loose  { padding-block: 4rem; }

/* ---- Unified intra-section spacing ----
   One rhythm for everything inside a section: 24px between stacked elements,
   32px before a sub-heading. Between sections, the 2.5rem padding gives ~80px. */
.section > * + *,
.section > .reading-column > * + *,
.section > .content-column > * + * { margin-block-start: var(--space-6); }

.section > * + :is(h2, h3, h4),
.section > .reading-column > * + :is(h2, h3, h4),
.section > .content-column > * + :is(h2, h3, h4) { margin-block-start: var(--space-8); }

/* First section after the page header gets less top padding so the hero
   sits closer to the top of the viewport. */
.section:first-child { padding-block-start: var(--space-12); }

/* Stack flow — vertical rhythm helper. Apply to a container to space
   children apart consistently without per-element margins. */
.stack > * + * {
  margin-block-start: var(--space-4);
}

.stack-sm > * + * { margin-block-start: var(--space-2); }
.stack-lg > * + * { margin-block-start: var(--space-8); }

/* Columns — equal columns for any number of children, which may shrink below
   their content (a plain 1fr track won't, and a native time field on iOS
   would push its neighbour off screen). */
.columns {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

/* Cluster — inline group with consistent gap (e.g. button rows). */
.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

.cluster-center { justify-content: center; }

/* Sticky CTA container — bottom of viewport on mobile, inline on desktop.
   Carol-rent calls this `.sticky-container`; same idea, cleaner. */
.sticky-cta {
  position: sticky;
  bottom: var(--space-4);
  z-index: 10;
  display: flex;
  justify-content: center;
  padding-block: var(--space-3);
}

/* Screen — a full-height, single-task view on a phone: a toolbar on top, a body
   that is the only thing that scrolls, and a footer pinned under the thumb.
   Put .narrow-column on the element that holds the three.

   <main class="screen"><div class="narrow-column screen-column">
     <header class="toolbar">…</header>
     <div class="screen-body" tabindex="0">…</div>
     <footer class="screen-footer">…</footer>
   </div></main> */
.screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  padding-block: var(--space-4);
}

.screen-column {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  min-height: 0;
}

.screen-body {
  flex-grow: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;   /* reaching the end doesn't drag the page */
  padding-block: var(--space-4);
}

/* The body clips its overflow, so its own focus ring is drawn inside it. */
.screen-body:focus-visible { outline-offset: -2px; }

.screen-footer {
  padding-block: var(--space-2) 0;
  background-color: var(--bg);
}

/* Toolbar — a back button and the screen's title on one line. */
.toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-md);
}

.toolbar-title {
  flex-grow: 1;
  margin: 0;
}

/* css/themes.css */
/**
 * Theme toggle helpers.
 *
 * Token-level theme switching is already wired in tokens.css (generated):
 *   - :root defaults to light
 *   - @media (prefers-color-scheme: dark) applies dark unless [data-theme="light"]
 *   - [data-theme="dark"] / [data-theme="light"] override the media query
 *
 * This file just adds smooth transitions and any theme-aware utilities
 * that aren't pure token swaps.
 */

html,
body {
  transition:
    background-color 0.2s ease,
    color 0.2s ease;
}

/* Disable transitions during initial theme-toggle to prevent FOUC flash.
   The scripts/theme.js helper adds .theme-init briefly on first toggle. */
.theme-init,
.theme-init *,
.theme-init *::before,
.theme-init *::after {
  transition: none !important;
}

/* color-scheme tells the browser to render form controls and scrollbars
   in the theme's palette. The value follows the active theme. */
:root              { color-scheme: light; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}
[data-theme="dark"]  { color-scheme: dark; }
[data-theme="light"] { color-scheme: light; }

/* Show/hide content based on active theme — useful for swapping icons
   in the theme-toggle button. Use sparingly. */
.theme-light-only,
.theme-dark-only { display: none; }

:root .theme-light-only { display: initial; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-light-only { display: none; }
  :root:not([data-theme="light"]) .theme-dark-only  { display: initial; }
}
[data-theme="dark"]  .theme-light-only { display: none; }
[data-theme="dark"]  .theme-dark-only  { display: initial; }
[data-theme="light"] .theme-light-only { display: initial; }
[data-theme="light"] .theme-dark-only  { display: none; }

/* components/button.css */
/**
 * Button — .btn family. Minimalist + neutral.
 *
 * Default .btn is a NATURAL neutral "ink" button (near-black on light,
 * near-white on dark) — the modern minimal look. The bluish primary accent
 * is reserved for links and the optional .btn-accent variant.
 *
 * Variants: default (ink) · .btn-accent (bluish) · .btn-secondary (outline) · .btn-ghost
 * Sizes:    .btn-xsmall (control-xs, 24px) · .btn-small (control-sm, 32px) · default (control-md, 40px)
 *           · .btn-large (control-lg, 48px) · .btn-xlarge (control-xl, 56px)
 *           Shared with .input, so a button and a field on one row line up.
 */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-md);    /* min, not fixed: stretches to a taller field in .input-group-inline */
  padding: 0 var(--control-pad-md);
  font-family: var(--font-serif);
  font-size: var(--text-base);
  font-weight: var(--font-weight-bold);
  line-height: 1.2;
  border-radius: var(--radius-control-md);
  border: var(--border-width) solid transparent;
  background-color: var(--ink);
  color: var(--ink_contrast) !important;
  text-decoration: none !important;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.btn:hover { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 20%, transparent), var(--shadow-sm); text-decoration: none; }
.btn:active { box-shadow: var(--shadow-sm); opacity: 0.9; }

.btn:disabled,
.btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; transform: none; }

/* ---- Variants ---- */

/* Colored accent button — reserved; chrome stays neutral by default. */
.btn-accent {
  background-color: var(--accent-primary);
}

/* Outline — neutral border, no shadow */
.btn-secondary {
  background-color: transparent;
  border-color: var(--border);
  color: var(--text) !important;
  box-shadow: none;
}
.btn-secondary:hover { border-color: var(--text); background-color: color-mix(in srgb, var(--ink) 5%, transparent); }

/* Ghost — text only */
.btn-ghost {
  background-color: transparent;
  border-color: transparent;
  color: var(--text) !important;
  box-shadow: none;
}
.btn-ghost:hover { background-color: var(--surface); opacity: 1; }

/* ---- Sizes ---- */

.btn-xsmall {
  min-height: var(--control-xs);
  padding-inline: var(--control-pad-xs);
  font-size: var(--text-xs);
  border-radius: var(--radius-control-xs);
}

.btn-small {
  min-height: var(--control-sm);
  padding-inline: var(--control-pad-sm);
  font-size: var(--text-sm);
  border-radius: var(--radius-control-sm);
}

.btn-large {
  min-height: var(--control-lg);
  padding-inline: var(--control-pad-lg);
  font-size: var(--text-lg);
  border-radius: var(--radius-control-lg);
}

.btn-xlarge {
  min-height: var(--control-xl);
  padding-inline: var(--control-pad-xl);
  font-size: var(--text-xl);
  border-radius: var(--radius-control-xl);
}

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

/* Icon only: square at any size. Give it a visually-hidden label. The icon
   scales with the size's text, so 20px at the default size. */
.btn-icon {
  aspect-ratio: 1;
  padding-inline: 0;
}

.btn-icon svg {
  width: 1.25em;
  height: 1.25em;
  flex-shrink: 0;
}

/* components/card.css */
/**
 * Card — minimalist. Flat by default (no shadow), thin border, subtle hover.
 * Left-aligned for single-column lists.
 *
 * Sub-elements: .card-header · .card-eyebrow · .card-icon · .card-title · .card-desc · .card-cta
 * Modifiers:    .card-interactive · .card-feature · .card-flat
 *
 * Container: .card-list — single-column stack of cards.
 */

.card-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-6);
  background: var(--surface);
  color: var(--text);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  text-decoration: none;
  text-align: left;
  transition: box-shadow 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}

/* A title (or its link) on the left and a badge or action on the right. */
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.card-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
}

.card-icon { font-size: var(--text-2xl); line-height: 1; }

.card-title {
  font-family: var(--font-serif);
  font-size: var(--text-xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-tight);
  color: var(--text);
  margin: 0;
}

.card-desc {
  font-size: var(--text-base);
  color: var(--text_body);
  line-height: var(--leading-normal);
}

.card-cta { margin-top: var(--space-2); }

/* ---- Modifiers ---- */

.card-interactive { cursor: pointer; }
.card-interactive:hover {
  border-color: color-mix(in srgb, var(--ink) 25%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 8%, transparent);
  background: var(--surface);
}

.card-feature { padding: var(--space-8); gap: var(--space-3); }
.card-feature .card-title { font-size: var(--text-2xl); }

.card-flat { background: var(--surface); }

/* components/input.css */
/**
 * Input — .input family.
 *
 * Generic .input for forms, plus .input-address — the hero address input
 * on the home page (large, prominent, paired with a submit button).
 */

.input {
  display: block;
  width: 100%;
  height: var(--control-md);
  padding: 0 var(--control-pad-md);
  font-family: var(--font-sans);
  font-size: var(--text-base);      /* 16px floor: iOS zooms into any smaller field */
  line-height: 1.25;
  color: var(--text);
  background: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-control-md);
  min-width: 0;                     /* shrinks inside grids and .columns */
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

textarea.input {
  height: auto;
  min-height: calc(var(--control-md) * 2);
  padding-block: var(--space-2);
  line-height: var(--leading-normal);
}

.input::placeholder {
  color: var(--muted);
  opacity: 1;
}

.input:hover {
  border-color: color-mix(in srgb, var(--muted) 50%, var(--border));
}

/* Focus is drawn inside the field, a doubled `text` border: an outer ring or
   halo gets clipped by any scrolling container the field sits in. */
.input:focus,
.input:focus-visible {
  outline: none;
  background-color: var(--bg);
  border-color: var(--text);
  box-shadow: inset 0 0 0 1px var(--text);
}

.input[aria-invalid="true"] { border-color: var(--accent-insight); }

.input[aria-invalid="true"]:focus {
  border-color: var(--accent-insight);
  box-shadow: inset 0 0 0 1px var(--accent-insight);
}

/* A select keeps the field's look and gets a chevron drawn from the palette. */
select.input {
  appearance: none;
  cursor: pointer;
  padding-inline-end: calc(var(--control-pad-md) + 1.25rem);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position:
    right calc(var(--control-pad-md) + 5px) center,
    right var(--control-pad-md) center;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}

/* iOS gives native time and date fields a minimum width and centres the
   value; without their native look they follow the field like any other. */
input.input[type="time"],
input.input[type="date"] {
  -webkit-appearance: none;
  appearance: none;
}

input.input::-webkit-date-and-time-value { text-align: start; }

/* The clear button of a search field, redrawn in `muted` instead of the
   browser's own accent colour. */
input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  width: 1rem;
  height: 1rem;
  background-color: var(--muted);
  cursor: pointer;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18 6 6 18M6 6l12 12' stroke='%23000' stroke-width='1.75' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18 6 6 18M6 6l12 12' stroke='%23000' stroke-width='1.75' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

input[type="search"]::-webkit-search-cancel-button:hover { background-color: var(--text); }

.input:disabled {
  background: var(--surface);
  cursor: not-allowed;
  opacity: 0.7;
}

/* ---- Address input (home hero) ---- */

.input-address {
  height: var(--control-lg);
  padding-inline: var(--control-pad-lg);
  font-size: var(--text-lg);
  border-radius: var(--radius-control-lg);
}

/* Form layout: input + submit on the same row at md+, stacked on mobile. */

.input-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
}

@media (min-width: 640px) {
  .input-group-inline {
    flex-direction: row;
  }
  .input-group-inline .input { flex: 1; }
}

/* Label + helper text */

/* Field: label, control, then helper or error, spaced as one unit. */
.field { display: block; }
.field + .field { margin-top: var(--space-4); }
.columns > .field { margin-top: 0; }   /* side by side, not stacked */

/* A label with an action at its right edge, usually an info button. */
.label-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.label-row > .input-label { margin-bottom: 0; }

.input-label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text);
  margin-bottom: var(--space-2);
}

.input-helper {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: var(--space-2);
}

.input-error {
  display: block;
  font-size: var(--text-xs);
  color: var(--accent-terracotta);
  margin-top: var(--space-2);
}

/* Input button — a <button> that looks like a field and opens a picker or a
   search: the value (or a .input-placeholder) on the left, an icon on the right.
   It grows past control-md when the value takes a second line (a place and
   its type). */
.input-button {
  height: auto;
  min-height: var(--control-md);
  padding-block: var(--space-1);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  text-align: start;
  cursor: pointer;
}

.input-button:hover { border-color: color-mix(in srgb, var(--muted) 50%, var(--border)); }
.input-button svg { width: 1.25em; height: 1.25em; flex-shrink: 0; }
.input-placeholder { color: var(--muted); }

/* Input box — one field drawn around a borderless input and its icon buttons
   (back, near me, clear). It takes focus as a whole, like an .input does. */
.input-box {
  display: flex;
  align-items: center;
  height: var(--control-md);
  padding-inline: var(--space-1);
  background-color: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-control-md);
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.input-box:hover { border-color: color-mix(in srgb, var(--muted) 50%, var(--border)); }

.input-box > input {
  flex-grow: 1;
  min-width: 0;
  height: 100%;
  padding-inline: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: 0;
  outline: none;
}

.input-box > input::placeholder { color: var(--muted); opacity: 1; }

.input-box:has(> input:focus-visible) {
  background-color: var(--bg);
  border-color: var(--text);
  box-shadow: inset 0 0 0 1px var(--text);
}

/* components/segmented.css */
/**
 * Segmented — pick one value from a few. Ported from Carol's condition
 * toggles (daily mileage, deposit, driver's age, transmission).
 *
 * Equal-width options on one row, any count (2–4 read best). Each is a
 * hairline chip; the selected one fills with fill-state, takes a `text`
 * border and goes bold, so the state never rests on the fill alone.
 *
 * Markup, preferred (native radios: no JS, arrow keys, form value):
 *   <fieldset>
 *     <legend class="input-label">Daily mileage</legend>
 *     <div class="segmented">
 *       <label class="segmented-option" title="150 km"><input type="radio" name="mileage" value="150" checked>150 km</label>
 *       …
 *     </div>
 *   </fieldset>
 * Also selected: <button class="segmented-option" aria-pressed="true"> and
 * <a class="segmented-option" aria-current="page"> for a tab strip.
 *
 * Size: one, the same as .btn-small (control-sm, 32px, text-sm). Options are
 * radios, not text fields, so the 16px field floor doesn't apply.
 */

.segmented {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);   /* equal columns that may shrink below their label */
  gap: var(--space-2);
}

.segmented-option {
  position: relative;
  display: block;
  height: var(--control-sm);
  padding: 0 var(--control-pad-sm);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: calc(var(--control-sm) - 2 * var(--border-width));
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;             /* one line; the full label goes in title="" */
  color: var(--text);
  background: transparent;
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-control-sm);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* The radio covers its label, invisible, so a click anywhere selects it. */
.segmented-option > input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: inherit;
}

.segmented-option:hover { border-color: color-mix(in srgb, var(--ink) 25%, transparent); }

.segmented-option[aria-pressed="true"],
.segmented-option[aria-current="page"],
.segmented-option:has(> input:checked) {
  background: var(--fill-state);
  border-color: var(--text);
  font-weight: var(--font-weight-bold);
}

.segmented-option:has(> input:focus-visible) {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

.segmented-option:disabled,
.segmented-option:has(> input:disabled) { opacity: 0.45; cursor: not-allowed; }

/* components/slider.css */
/**
 * Slider — horizontal scroll-snap row of cards. Adapted from carol-rent,
 * rebuilt on design-system tokens.
 *
 * Markup:
 *   <div class="slider">
 *     <div class="slider-track">
 *       <div class="slider-item"><a class="card">…</a></div>
 *       …
 *     </div>
 *   </div>
 *
 * Hidden scrollbar, scroll-snap, and a soft edge-fade mask so partially
 * scrolled cards fade out at the container edges.
 */

.slider {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 0;
  padding-block: var(--space-2);
  /* Left edge stays crisp so the first card aligns with section content;
     only the right edge fades to signal more cards. */
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - var(--space-12)), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - var(--space-12)), transparent 100%);
}

.slider::-webkit-scrollbar { display: none; }

.slider-track {
  display: flex;
  align-items: stretch;
  gap: var(--space-3);
  width: max-content;
  max-width: none;
  padding-inline: 0;
  margin: 0;
}

.slider-item {
  flex: 0 0 13rem;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

/* Card fills its slider cell so a row is visually even. */
.slider-item > .card {
  height: 100%;
}

/* Square cards: emoji top zone (55%) + text bottom zone (45%). */
.slider-item > .card-square {
  height: auto;
  aspect-ratio: 1 / 1;
  display: grid;
  grid-template-rows: 55fr 45fr;
  text-align: left;
  gap: var(--space-1);
  padding: var(--space-4);
}
.card-square .card-icon { align-self: end; justify-self: start; font-size: var(--text-3xl); line-height: 1; }
.card-square .card-title { font-family: var(--font-serif); font-size: var(--text-lg); font-weight: var(--font-weight-bold); align-self: start; justify-self: start; }
.card-square .card-desc { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--muted); }

@media (max-width: 640px) {
  .slider-item { flex-basis: 11rem; }
}

/* components/option-list.css */
/**
 * Option list — pick one row from a list of rich options: car groups, search
 * results, saved places. Ported from Carol's car groups and location results.
 *
 * <ul class="option-list">
 *   <li><button class="option-row" aria-pressed="true">
 *     <span class="option-body">
 *       <span class="option-title">Small</span>
 *       <span class="option-meta">4 seats · 2 doors</span>
 *     </span>
 *     <img class="option-media car-image" src="small.webp" alt="">
 *   </button></li>
 * </ul>
 *
 * The title wears the link underline (a tappable word); the selected row fills
 * with fill-state, takes a `text` border and a bold title, like .segmented.
 * Selected: aria-pressed="true", aria-selected="true", aria-current, or a
 * checked radio inside a <label class="option-row">.
 */

.option-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.option-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font: inherit;
  text-align: start;
  color: var(--text);
  background: transparent;
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.option-row > input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: inherit;
}

.option-row:hover { border-color: color-mix(in srgb, var(--ink) 25%, transparent); }

.option-body {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  min-width: 0;
  gap: var(--space-1);
}

.option-title {
  font-weight: var(--font-weight-semibold);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--border);
  text-underline-offset: 0.18em;
  transition: text-decoration-color 0.15s ease;
}

.option-row:hover .option-title { text-decoration-color: currentColor; }

.option-meta {
  font-size: var(--text-xs);
  color: var(--muted);
}

.option-media { flex-shrink: 0; }

.option-row[aria-pressed="true"],
.option-row[aria-selected="true"],
.option-row[aria-current]:not([aria-current="false"]),
.option-row:has(> input:checked) {
  background: var(--fill-state);
  border-color: var(--text);
}

.option-row[aria-pressed="true"] .option-title,
.option-row[aria-selected="true"] .option-title,
.option-row[aria-current]:not([aria-current="false"]) .option-title,
.option-row:has(> input:checked) .option-title {
  font-weight: var(--font-weight-bold);
  text-decoration: none;
}

.option-row:has(> input:focus-visible) {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

/* Car photos from the Cars set, at their shared scale. */
.car-image {
  width: 144px;
  height: 68px;
  object-fit: contain;
  object-position: bottom;
}

.car-image-small {
  width: 102px;
  height: 48px;
}

/* components/details.css */
/**
 * Details — label and value pairs read down a page: a booking's terms, a
 * card's facts, a price line. Ported from Carol's rows and conditions table.
 *
 * <dl class="details">
 *   <div class="details-row"><dt>Deposit</dt><dd>$1,000.00</dd></div>
 *   <div class="details-row details-total"><dt>Total</dt><dd>$284.58</dd></div>
 * </dl>
 *
 * Label muted on the left, value in `text` on the right, a hairline between
 * rows. .details-total closes a list with the sum, set in the serif.
 */

.details { margin: 0; }

.details-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-2);
}

.details-row + .details-row { border-top: var(--border-width) solid var(--border); }

.details-row > dt {
  font-size: var(--text-sm);
  color: var(--muted);
}

.details-row > dd {
  margin: 0;
  font-weight: var(--font-weight-semibold);
  text-align: end;
}

.details-total > dt,
.details-total > dd {
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  color: var(--text);
}

.details-total { padding-block: var(--space-3); }

/* components/badge.css */
/**
 * Badge — a short status or tag beside a title: Active, Confirmed, UA.
 * Ported from Carol's status chip.
 *
 * <span class="badge">Confirmed</span>
 *
 * A pill on fill-state in `text`, 24px tall (control-xs). One neutral look:
 * the word carries the meaning, never a colour.
 */

.badge {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-xs);
  padding-inline: var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
  white-space: nowrap;
  color: var(--text);
  background: var(--fill-state);
  border-radius: var(--radius-pill);
}

/* components/callout.css */
/**
 * Callout — a reassurance or aside set off from the flow: an icon, a short
 * serif title and a caption. Ported from Carol's "Privacy protected" note.
 *
 * <aside class="callout">
 *   <svg class="callout-icon" …></svg>
 *   <div><p class="callout-title">Privacy protected</p>
 *   <p class="callout-text">…</p></div>
 * </aside>
 *
 * No fill, no coloured edge: the icon and the title set it apart.
 */

.callout {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
}

.callout-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin-top: 2px;
  color: var(--text);
}

.callout-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--text-lg);
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-tight);
  color: var(--text);
}

.callout-text {
  margin: var(--space-1) 0 0;
  font-size: var(--text-xs);
  color: var(--muted);
}

/* components/empty-state.css */
/**
 * Empty state — the whole view is one message: loading, nothing found, an
 * error with a retry, a booking's outcome, a 404. Ported from Carol's
 * flow-state, Loading, ErrorState and NotFound.
 *
 * <div class="empty-state">
 *   <h2 class="h3">Nothing is found</h2>
 *   <p class="muted">There are no free cars that match your request.</p>
 *   <button class="btn">Try again</button>
 * </div>
 *
 * Centred on both axes in at least 60% of the viewport; add
 * .empty-state-inline to sit in the flow of a page instead.
 */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  min-height: 60vh;
  text-align: center;
}

.empty-state > * { margin: 0; max-width: var(--width-narrow); }

.empty-state-inline { min-height: 0; padding-block: var(--space-8); }

/* components/progress.css */
/**
 * Progress — three ways to say "not there yet".
 *
 *   .progress-steps   where a flow is: one 2px segment per step, done in `ink`.
 *   .loading-bar      something is on its way, time unknown: a 2px ink runner.
 *   .skeleton         a value is on its way: a shimmering block its size.
 *
 * <div class="progress-steps" role="progressbar" aria-valuenow="2" aria-valuemin="1" aria-valuemax="5">
 *   <span class="progress-step progress-step-done"></span><span class="progress-step"></span>…
 * </div>
 * <div class="loading-bar" role="status" aria-label="Loading"></div>
 * <span class="skeleton" style="width: 12ch"></span>
 *
 * All motion stops under prefers-reduced-motion (the reset handles it).
 */

.progress-steps {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--space-2);
}

.progress-step {
  height: 2px;
  background-color: var(--fill-state);
}

.progress-step-done { background-color: var(--ink); }

.loading-bar {
  position: relative;
  height: 2px;
  overflow: hidden;
}

.loading-bar::before {
  content: "";
  position: absolute;
  inset-block: 0;
  width: 20%;
  background-color: var(--ink);
  animation: kinda-loading-bar 0.6s ease-in-out infinite alternate;
}

@keyframes kinda-loading-bar {
  from { left: 0; }
  to { left: 80%; }
}

.skeleton {
  display: inline-block;
  height: 1.25em;
  min-width: 4ch;
  vertical-align: middle;
  border-radius: var(--radius-control-xs);
  background: linear-gradient(-90deg, var(--surface) 25%, var(--fill-state) 50%, var(--surface) 75%);
  background-size: 200% 100%;
  animation: kinda-skeleton 1.5s infinite;
}

@keyframes kinda-skeleton {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

/* components/calendar.css */
/**
 * Calendar — a scrolling month list for picking a date range. Ported from
 * Carol's range calendar; the app supplies the dates and the picking logic.
 *
 * <div class="calendar">
 *   <div class="calendar-weekdays"><span>Mon</span>…</div>
 *   <div class="calendar-months">
 *     <p class="eyebrow calendar-month-title">September 2026</p>
 *     <div class="calendar-grid">
 *       <button class="calendar-day" disabled>1</button>
 *       <button class="calendar-day" aria-current="date">26</button>
 *       <button class="calendar-day calendar-day-start" aria-pressed="true">27</button>
 *       <button class="calendar-day calendar-day-in-range">28</button>
 *       <button class="calendar-day calendar-day-end" aria-pressed="true">30</button>
 *     </div>
 *   </div>
 * </div>
 *
 * Open days wear the link underline; today has a faint ring; the picked ends
 * are `ink` like the primary button; the days between take fill-state.
 */

.calendar {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.calendar-weekdays,
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

.calendar-weekdays {
  padding-block: var(--space-2);
  font-size: var(--text-xs);
  text-align: center;
  color: var(--muted);
  border-bottom: var(--border-width) solid var(--border);
}

.calendar-months {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  position: relative;               /* the offsetParent a month's scroll position is read from */
}

.calendar-month-title { margin: var(--space-6) 0 var(--space-3); }

.calendar-grid { row-gap: 2px; }

.calendar-day {
  height: var(--control-md);
  padding: 0;
  font: inherit;
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: var(--radius-control-md);
  cursor: pointer;
  outline-offset: -2px;             /* drawn inside, or the scrolling list clips it */
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--border);
  text-underline-offset: 0.18em;
}

.calendar-day:disabled {
  cursor: default;
  opacity: 0.45;
  text-decoration: none;
}

.calendar-day[aria-current="date"] {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 25%, transparent);
}

@media (hover: hover) {
  .calendar-day:not(:disabled):hover {
    text-decoration-color: currentColor;
    box-shadow: inset 0 0 0 1px var(--text);
  }
}

.calendar-day-in-range {
  background: var(--fill-state);
  border-radius: 0;
  text-decoration: none;
}

.calendar-day-start,
.calendar-day-end {
  color: var(--ink_contrast);
  font-weight: var(--font-weight-bold);
  background: var(--ink);
  text-decoration: none;
  border-radius: 0;
}

.calendar-day-start {
  border-start-start-radius: var(--radius-control-md);
  border-end-start-radius: var(--radius-control-md);
}

.calendar-day-end,
.calendar-day-start.calendar-day-end {
  border-start-end-radius: var(--radius-control-md);
  border-end-end-radius: var(--radius-control-md);
}

/* components/map.css */
/**
 * Map — a frame for an embedded OpenFreeMap / MapLibre map, a placeholder while
 * it loads, a marker for a place, and a skin for MapLibre's attribution.
 * Ported from Carol's map panel.
 *
 * <div class="map-frame" style="height: 240px">
 *   <div id="map"></div>
 *   <div class="map-placeholder">Loading map…</div>
 * </div>
 *
 * Load Positron in light and Dark in dark (see the brand book), so everything
 * here reads the current theme's tokens, like the page around it.
 */

.map-frame {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
}

.map-frame > :first-child { width: 100%; height: 100%; }

.map-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  font-size: var(--text-sm);
  text-align: center;
  color: var(--muted);
  background: var(--surface);
}

/* A place with real extent (a city, an airport): a dot on its centre, softer
   than a pin on purpose. */
.map-marker {
  width: 12px;
  height: 12px;
  background: var(--accent-indigo);
  border: 2px solid var(--bg);
  border-radius: 50%;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-indigo) 16%, transparent);
}

/* MapLibre's attribution, kept (it is required) but quiet: collapsed to a
   24px round button, expanded into a translucent pill. */
.map-frame .maplibregl-ctrl-attrib.maplibregl-compact { margin: 0 var(--space-2) var(--space-2) 0; }

.map-frame .maplibregl-ctrl-attrib.maplibregl-compact:not([open]) {
  width: 24px;
  height: 24px;
  min-height: 0;
  padding: 0;
  background: none;
  box-shadow: none;
}

.map-frame .maplibregl-ctrl-attrib.maplibregl-compact[open] {
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border-radius: var(--radius-pill);
}

.map-frame .maplibregl-ctrl-attrib .maplibregl-ctrl-attrib-button {
  background-color: color-mix(in srgb, var(--bg) 88%, transparent);
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 1px var(--border);
}

.map-frame .maplibregl-ctrl-attrib-inner,
.map-frame .maplibregl-ctrl-attrib-inner a {
  font-size: 0.6875rem;
  line-height: 1.4;
  color: var(--muted);
}

.map-frame .maplibregl-ctrl-logo { display: none; }

/* components/prose.css */
/**
 * Prose — long-form text written as plain HTML: terms, policies, articles.
 * Gives paragraphs, headings, lists and definition lists their rhythm and
 * puts back the list markers the reset takes away. Ported from Carol's terms.
 *
 * <article class="prose"><h2>Terms of Service</h2><p>…</p><ul><li>…</li></ul></article>
 */

.prose { color: var(--text_body); }

.prose > * + * { margin-top: var(--space-3); }
.prose > * + :is(h2, h3, h4, h5) { margin-top: var(--space-8); }
.prose > :is(h2, h3, h4, h5) + * { margin-top: var(--space-2); }

.prose ul { list-style: disc; padding-inline-start: var(--space-6); }
.prose ol { list-style: decimal; padding-inline-start: var(--space-6); }
.prose li + li { margin-top: var(--space-1); }

.prose dt {
  font-weight: var(--font-weight-bold);
  color: var(--text);
}

.prose dd { margin: 0 0 var(--space-2); }
