:root {
  --bg: #f6f1e6; --surface: #fffdf8; --text: #2a2620; --text-muted: #75695a;
  --accent: #c9722f; --accent-contrast: #fffaf3; --primary: #33513a;
  --border: #e3d9c4; --error: #a3372a; --ok: #2f6f4f;
  --shadow: 0 1px 2px rgba(50, 40, 20, .05), 0 6px 16px rgba(50, 40, 20, .08);
  --radius: 8px;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1f1a; --surface: #222922; --text: #eee8da; --text-muted: #a49d8c;
    --accent: #e08a48; --accent-contrast: #241505; --primary: #8fb89a;
    --border: #333b31; --error: #ff9a85; --ok: #7fc79b;
    --shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 6px 18px rgba(0, 0, 0, .4);
  }
}
* { box-sizing: border-box; }
/* The flex column exists only so the footer can take margin-top:auto and sit
   at the bottom of a short page instead of floating directly under whatever
   content happens to end last. With the FAQ collapsed the page is shorter
   than most screens, so without this the footer drifted down every time a
   question was opened. 100dvh rather than 100vh because mobile browser
   chrome makes 100vh taller than the visible viewport. */
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  max-width: 680px; margin: 0 auto; padding: 2.5rem 1rem 3rem;
  background: var(--bg);
  color: var(--text); line-height: 1.55;
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column;
}
/* Flex items don't shrink-to-fit their content the way block children do,
   and a column flex item's `flex-basis` is its HEIGHT. Neither default is
   wanted for ordinary page content, so opt every direct child out. */
body > * { flex: 0 0 auto; }
header.brand { display: flex; align-items: center; gap: 0.55rem; font-weight: 700; font-size: 1.08rem; margin-bottom: 1.6rem; color: var(--primary); }
header.brand .brand-icon { display: block; flex-shrink: 0; }
/* The destination dot is the accent, matching the og card and the endpoint
   dots on the route preview, where the amber end has always marked where
   you are going. The header mark was the one place both dots were the same
   colour. Set here rather than as a fill attribute so it follows the theme:
   var() is not reliably substituted in a presentation attribute, and the
   currentColor fill stays as the fallback for anywhere the rule does not
   reach. */
header.brand .brand-icon .brand-end { fill: var(--accent); }
/* Tighter than the body's 1.55: the headline is one line on a desktop and
   wraps to two on a phone, and the default leading is too airy for both. */
h1 { font-size: 1.5rem; margin: 0 0 0.6rem; letter-spacing: -0.01em; line-height: 1.25; color: var(--text); }
p.hint { color: var(--text-muted); font-size: 0.92rem; margin: 0 0 1.4rem; }
p.lede { font-size: 1.02rem; margin: 0 0 1.5rem; text-wrap: pretty; }
p.eyebrow { margin: 0 0 0.3rem; font-size: 0.72rem; font-weight: 600;
            letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); }
input[type=text] {
  width: 100%; padding: 0.75rem 0.9rem; font-size: 1rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text); box-sizing: border-box;
}
input[type=text]:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
button {
  margin-top: 1rem; padding: 0.7rem 1.3rem; font-size: 0.95rem; font-weight: 600;
  cursor: pointer; background: var(--accent); color: var(--accent-contrast);
  border: none; border-radius: var(--radius);
}
.error { color: var(--error); margin-top: 1rem; font-size: 0.9rem; }
.option {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 1rem 1.15rem; margin-bottom: 0.9rem;
}
.option h2 { font-size: 1rem; margin: 0 0 0.7rem; font-weight: 600; color: var(--primary); }
/* The result page's two buttons per option. They used to be inline forms
   spaced by margin-right, which collided on a phone: an inline-block taller
   than the line-height overlaps the next line box when it wraps. */
.actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
/* Send starts disabled until resume.js installs the handler that preserves
   the route across OAuth. Keep the fallback state visibly unavailable. */
button:disabled { background: var(--surface); color: var(--text-muted);
                  border: 1px solid var(--border); cursor: not-allowed; }
/* The route's own shape, drawn server side from the polyline. `height: auto`
   with an explicit viewBox lets it scale down on a phone without a media
   query. The muted stroke keeps it as orientation rather than decoration:
   it is there to be recognised at a glance, not read. */
.preview {
  display: block; width: 100%; height: auto; margin: 0 0 0.9rem;
  color: var(--text-muted); overflow: visible;
}
.preview-start { fill: var(--ok); }
.preview-end { fill: var(--accent); }
/* Sits above the buttons: a rename after clicking is too late. The styling
   is doing one job, which is making it obvious the value can be changed. A
   bordered box holding text that is also printed in the heading right above
   reads as a restatement, so the label, the full input chrome and the accent
   focus ring all have to say "field" loudly enough to overcome that. */
.rename { display: flex; flex-direction: column; gap: 0.3rem; margin: 0 0 0.9rem; }
.rename label { font-size: 0.78rem; font-weight: 600; color: var(--text); }
.rename input[type=text] { padding: 0.55rem 0.7rem; font-size: 0.95rem; }
.rename-hint { font-size: 0.78rem; color: var(--text-muted); }
/* Input and button on one row. flex-basis 15rem keeps the URL field from
   being squeezed to nothing; stretch alignment matches their heights even
   though their padding and font sizes differ. Two-value gap is deliberate:
   0.85rem between the rows once stacked, 0.5rem between them side by side.
   A single value made the stacked gap 8px, tighter than the margin the
   button had before it moved inline. */
.field { display: flex; gap: 0.85rem 0.5rem; flex-wrap: wrap; align-items: stretch; margin-bottom: 1.3rem; }
.field input[type=text] { flex: 1 1 15rem; min-width: 0; }
.field button { margin-top: 0; flex-shrink: 0; white-space: nowrap; }
/* Below this the pair stacks, and align-items: stretch full-widths both.
   A natural-width button under a full-width input reads as an orphan, and
   it's a poor tap target at the one size where taps are how you use it.
   flex-wrap above stays as a safety net if a longer label wraps earlier.

   The input's flex MUST be reset here. flex-basis sets the MAIN size, and
   switching to a column makes that the height, so the 15rem written above
   to mean "don't squeeze the field narrower than 240px" silently became a
   240px-TALL input. Shipped that way once; it looked like a textarea. */
@media (max-width: 440px) {
  .field { flex-direction: column; }
  .field input[type=text] { flex: 0 0 auto; }
}
.option button { margin-top: 0; padding: 0.55rem 1rem; font-size: 0.9rem; }
a { color: var(--accent); }
a.connect { font-size: 0.9rem; }
/* No bottom margin: the widget is the last thing in the form, and a flex
   item establishes its own block formatting context, so once body became a
   flex column this margin stopped collapsing away and started adding to the
   form's height instead. */
.cf-turnstile { margin: 0.85rem 0 0; }
/* A completed step, styled to sit above the Turnstile box as its pair. The
   300px is Turnstile's own rendered width: a soft dependency on someone
   else's layout, so if Cloudflare changes it these stop lining up, which is
   cosmetic rather than broken. */
.done { display: flex; align-items: center; gap: 0.5rem; max-width: 300px;
        margin: 0.85rem 0; padding: 0.6rem 0.75rem;
        border: 1px solid var(--border); border-radius: var(--radius);
        background: var(--surface); font-size: 0.9rem; }
.done svg { flex-shrink: 0; color: var(--ok); }
.done span { flex-grow: 1; }
/* A button because disconnect changes state and must be a POST, styled as a
   link because it is a quiet escape hatch, not an action to invite. */
button.linkish { margin: 0; padding: 0; border: 0; background: none;
                 color: var(--text-muted); font: inherit; font-size: 0.85rem;
                 text-decoration: underline; cursor: pointer; }
button.linkish:hover { color: var(--accent); }
/* Content below the form: the part search engines actually read. */
/* 2.6rem when this margin still collapsed against the form's; as a flex item
   it is the whole gap on its own, so it comes down to match what the page
   used to look like. */
section { margin-top: 1.9rem; }
h2 { font-size: 1.15rem; margin: 0 0 0.6rem; color: var(--primary); letter-spacing: -0.01em; }
code { font-size: 0.88em; background: var(--surface); border: 1px solid var(--border);
       border-radius: 4px; padding: 0.08em 0.32em; overflow-wrap: anywhere; }
.faq details { border-bottom: 1px solid var(--border); }
.faq details:first-of-type { border-top: 1px solid var(--border); }
.faq summary { cursor: pointer; padding: 0.7rem 0; font-weight: 600; font-size: 0.95rem;
               list-style: none; display: flex; justify-content: space-between; gap: 1rem; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-weight: 700; }
.faq details[open] summary::after { content: "\2212"; }
.faq summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.faq details p { margin: 0 0 0.9rem; color: var(--text-muted); font-size: 0.92rem; }
.banner { background: var(--surface); border: 1px solid var(--primary);
          border-radius: var(--radius); padding: 0.75rem 1rem; margin-bottom: 1.2rem; font-size: 0.93rem; }
footer { margin-top: auto; padding-top: 2.5rem; }
footer p.hint { margin: 0; font-size: 0.85rem; }
