/* ojhej.se stylesheet
   Aesthetic: Swedish editorial minimalism. Ink on warm paper, one accent, hairline rules,
   spec-sheet typography. The QR finder pattern is the recurring mark.

   Fonts are still loaded from the Google CDN. Self-hosting them is a launch blocker, not a
   nicety: a third-party font request undercuts the EU-only, no-cookie-banner posture that
   drove the whole hosting choice. See R20 in status.md. */

:root {
  --paper: #f7f6f2;
  --paper-sunk: #efeee8;
  --ink: #12100e;
  --ink-soft: rgba(18, 16, 14, 0.56);
  --ink-faint: rgba(18, 16, 14, 0.34);
  --rule: rgba(18, 16, 14, 0.14);
  --rule-strong: rgba(18, 16, 14, 0.26);
  --accent: #d8452b;
  --accent-ink: #f7f6f2;

  --font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --font-ui: "Familjen Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --gutter: clamp(1.5rem, 6vw, 3.5rem);
  --measure: 34rem;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #12100e;
    --paper-sunk: #1a1815;
    --ink: #f2f0ea;
    --ink-soft: rgba(242, 240, 234, 0.58);
    --ink-faint: rgba(242, 240, 234, 0.34);
    --rule: rgba(242, 240, 234, 0.16);
    --rule-strong: rgba(242, 240, 234, 0.3);
    --accent: #ff6a4d;
    --accent-ink: #12100e;
  }
}

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

/* The user-agent rule for [hidden] is display:none at the lowest specificity, so any class that
   sets display beats it. .field sets display:block, which made a hidden field render anyway. */
[hidden] {
  display: none !important;
}

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

body {
  margin: 0;
  min-height: 100svh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 1.0625rem;
  line-height: 1.5;
  font-feature-settings: "ss01" 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Paper grain. Atmosphere without an image request. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 100;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- layout ---------- */

.wrap {
  width: 100%;
  max-width: 30rem;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.screen {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}

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

.pad-top {
  padding-top: clamp(2rem, 9vh, 5rem);
}

.pad-bottom {
  padding-bottom: clamp(2rem, 9vh, 5rem);
}

.grow {
  flex: 1;
}

/* ---------- the mark: a QR finder pattern ---------- */

.mark {
  display: block;
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
}

.mark rect {
  fill: var(--ink);
}

.mark--accent rect {
  fill: var(--accent);
}

/* ---------- typography ---------- */

.eyebrow {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}

.statement {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(4.25rem, 21vw, 8.5rem);
  line-height: 0.82;
  letter-spacing: -0.025em;
  margin: 0;
}

.headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.5rem, 11vw, 4rem);
  line-height: 0.94;
  letter-spacing: -0.02em;
  margin: 0;
}


.lede {
  font-size: 1.1875rem;
  line-height: 1.42;
  color: var(--ink-soft);
  max-width: var(--measure);
  margin: 0;
  text-wrap: pretty;
}

.aside {
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--ink-faint);
  margin: 0;
  text-wrap: pretty;
}

.dry {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.125rem;
  color: var(--ink-faint);
  margin: 0;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: var(--rule-strong);
}

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

.stack > * + * {
  margin-top: var(--s, 1.25rem);
}

.stack-s {
  --s: 0.6rem;
}

.stack-l {
  --s: 2rem;
}

.stack-xl {
  --s: 3rem;
}

/* ---------- rules & spec sheet ---------- */

.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 0;
}

.spec {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.7rem 0;
  border-top: 1px solid var(--rule);
  font-size: 0.9375rem;
}

.spec:last-child {
  border-bottom: 1px solid var(--rule);
}

.spec dt {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
  flex: none;
}

.spec .leader {
  flex: 1;
  border-bottom: 1px dotted var(--rule-strong);
  transform: translateY(-0.2em);
}

.spec dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}


/* ---------- controls ---------- */

.btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  min-height: 3.5rem;
  padding: 0 1.5rem;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: inherit;
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 0.18s var(--ease), background 0.18s var(--ease),
    border-color 0.18s var(--ease);
}

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

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

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}

.btn--ghost:hover {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
}

.btn--danger:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}


/* A row of small actions. The full-width .btn is for the one thing a page is asking for. */
.btn--tiny {
  width: auto;
  min-height: 2.5rem;
  padding: 0 0.9rem;
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
}

/* ---------- chips: one choice out of a few ---------- */

/* The purpose picker and the background choice on /klar. Both pages emitted .chips and .chip
   long before this file had a rule for either, so the background choice rendered as two default
   browser buttons inside a designed form. */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.chip {
  appearance: none;
  border: 1px solid var(--rule-strong);
  border-radius: 0;
  background: transparent;
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 0.55rem 0.9rem;
  cursor: pointer;
  transition: background 0.18s var(--ease), color 0.18s var(--ease),
    border-color 0.18s var(--ease);
}

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

.chip[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.chip[aria-pressed="true"]:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* ---------- primary choices ---------- */

.choice-fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.choice-cards,
.mode-cards {
  display: grid;
  gap: 0.65rem;
}

.choice-card,
.mode-card {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  width: 100%;
  padding: 1rem;
  border: 1px solid var(--rule-strong);
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease);
}

.choice-card:hover,
.mode-card:hover {
  border-color: var(--accent);
}

.choice-card:has(input:checked),
.mode-card[aria-pressed="true"] {
  border-color: var(--ink);
  background: var(--paper-sunk);
  box-shadow: inset 3px 0 0 var(--accent);
}

.choice-card input {
  flex: none;
  margin: 0.25rem 0 0;
  accent-color: var(--accent);
}

/* A choice card is a label inside `.field`; undo the compact all-caps field-label treatment. */
.field .choice-card {
  display: flex;
  margin-bottom: 0;
  color: var(--ink);
  font-size: inherit;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

.choice-card span,
.mode-card span {
  display: grid;
  gap: 0.2rem;
}

.choice-card strong,
.mode-card strong {
  font-size: 1rem;
  line-height: 1.3;
}

.choice-card small,
.mode-card span {
  color: var(--ink-faint);
  font-size: 0.8125rem;
  line-height: 1.4;
}

.mode-card {
  display: grid;
  gap: 0.2rem;
}

/* ---------- survey builder and answers ---------- */

.survey-builder {
  padding: 1.25rem;
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
}

.section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.section-head .legend,
.section-head .hint {
  margin-top: 0;
}

.questions {
  display: grid;
  gap: 1.15rem;
}

.question-row label {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--ink-faint);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.question-control {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
}

.question-control .input {
  flex: 1;
}

.remove-question {
  flex: none;
  border: 0;
  background: transparent;
  color: var(--ink-faint);
  font: inherit;
  font-size: 0.75rem;
  padding: 0.75rem 0;
  cursor: pointer;
}

.remove-question:hover:not(:disabled) {
  color: var(--accent);
}

.remove-question:disabled {
  opacity: 0.35;
  cursor: default;
}

.survey-builder > .aside {
  margin-top: 1rem;
}

.survey-progress {
  padding: 1rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.survey-progress .aside {
  margin-top: 0.35rem;
}

.survey-answer .survey-question {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.2;
  text-transform: none;
}

.survey-question span {
  color: var(--accent);
  font-family: var(--font-ui);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
}

/* ---------- what the scanner will read ---------- */

/* Dashed rather than solid: this is a preview of another page, not a control on this one. */
.forhands {
  padding: 1.1rem 1.25rem;
  border: 1px dashed var(--rule-strong);
  background: var(--paper-sunk);
}

.forhands .rad {
  font-size: 1.0625rem;
  line-height: 1.4;
  color: var(--ink);
  margin: 0.4rem 0 0;
  text-wrap: pretty;
}

.forhands .rad--tom {
  color: var(--ink-faint);
  font-family: var(--font-display);
  font-style: italic;
}

/* ---------- a code in a list of codes ---------- */

.kod {
  padding: 1.35rem 0;
  border-top: 1px solid var(--rule);
}

.kod:last-of-type {
  border-bottom: 1px solid var(--rule);
}

.kod-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

.kod-namn {
  font-family: var(--font-display);
  font-size: 1.625rem;
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 0;
}

.kod-status {
  margin-left: auto;
  flex: none;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.kod-adress {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--ink-faint);
  overflow-wrap: anywhere;
  margin: 0.5rem 0 0;
}

.kod-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.9rem;
}

:where(a, button, input, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ---------- form ---------- */

.field {
  display: block;
}

.field + .field {
  margin-top: 1.5rem;
}

.field label,
.legend {
  display: block;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.5rem;
}

.input,
.textarea {
  width: 100%;
  padding: 0.75rem 0;
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 1.125rem;
  line-height: 1.4;
  transition: border-color 0.18s var(--ease);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--ink-faint);
}

.input:focus,
.textarea:focus {
  outline: 0;
  border-bottom-color: var(--accent);
}

.textarea {
  resize: vertical;
  min-height: 6rem;
}

.hint {
  margin: 0.5rem 0 0;
  font-size: 0.8125rem;
  color: var(--ink-faint);
}

.counter {
  float: right;
  font-variant-numeric: tabular-nums;
}

/* honeypot: present in the DOM, invisible and unfocusable for humans */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* segmented control for contact channel */
.seg {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--rule-strong);
}

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

.seg label {
  margin: 0;
  padding: 0.75rem 0.25rem;
  text-align: center;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}

.seg label + label {
  border-left: 1px solid var(--rule-strong);
}

.seg input:checked + label {
  background: var(--ink);
  color: var(--paper);
}

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

/* ALTCHA stand-in */
.altcha {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
  font-size: 0.875rem;
  color: var(--ink-soft);
}

.altcha .tick {
  color: var(--accent);
  font-weight: 700;
}

.altcha .brand {
  margin-left: auto;
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ---------- slug / code box ---------- */

.slug {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--rule-strong);
  background: var(--paper-sunk);
}

/* The address gets its own full-width row so a random slug never breaks mid-token. */
.slug code {
  flex: 1 1 100%;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.8125rem;
  letter-spacing: 0.01em;
  overflow-wrap: anywhere;
  line-height: 1.35;
}

.copy {
  flex: none;
  appearance: none;
  border: 1px solid var(--rule-strong);
  background: transparent;
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.45rem 0.6rem;
  cursor: pointer;
}

.copy:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* ---------- qr preview ---------- */

.qr-frame {
  display: grid;
  place-items: center;
  padding: 1.75rem;
  background: #fff;
  border: 1px solid var(--rule-strong);
}

/* Stand-in for the garment colour selected in the designer. */
.qr-frame.on-dark {
  background: #171512;
  border-color: #171512;
}

.qr-frame {
  position: relative;
}

.qr-frame.is-updating::after {
  content: "Uppdaterar …";
  position: absolute;
  right: 0.75rem;
  bottom: 0.65rem;
  padding: 0.25rem 0.45rem;
  background: rgba(255, 255, 255, 0.92);
  color: #12100e;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.qr-frame img,
.qr-frame svg {
  width: 100%;
  max-width: 15rem;
  height: auto;
  display: block;
}

.dl {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 0;
  border-top: 1px solid var(--rule);
  text-decoration: none;
}

/*
 * No closing rule on the last row.
 *
 * Every row draws its own top border, so a list already has a line above each item including
 * the first. A closing border underneath then lands directly on the footer's top border and
 * renders as two lines with a gap between them, which reads as a mistake because it is one.
 * The footer's rule closes the list. Both places that use these rows sit last on their page,
 * so this holds everywhere it is used today.
 */

.dl-name {
  font-weight: 600;
  font-size: 0.9375rem;
}

.dl-meta {
  font-size: 0.75rem;
  color: var(--ink-faint);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.dl-fmt {
  margin-left: auto;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  flex: none;
}

/* ---------- notice / status ---------- */

.notice {
  padding: 1rem 1.15rem;
  border-left: 2px solid var(--accent);
  background: var(--paper-sunk);
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

.dot {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  background: var(--accent);
  margin-right: 0.5rem;
  vertical-align: 0.05em;
}

.dot--off {
  background: var(--ink-faint);
}

/* ---------- footer ---------- */

.foot {
  padding: 2rem 0 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.8125rem;
  color: var(--ink-faint);
  line-height: 1.45;
}

/*
 * The count, as a folio.
 *
 * It has been three things now. A faint aside under the call to action, where it sat beneath a
 * line in the same faint italic and disappeared. Then a stat block with a rule, which was
 * visible but argued a case nobody asked it to argue. Now a folio in the corner, which is what
 * it always was: a small pleasing fact, found rather than presented.
 *
 * Absolutely positioned so it holds the corner regardless of the hero being vertically centred,
 * and pointer-events: none so it can never sit between a reader and anything they meant to
 * click. It is not a link and should not behave like one.
 */
.screen--folio {
  position: relative;
}

.folio {
  position: absolute;
  top: clamp(1.25rem, 4vh, 2.25rem);
  /* Aligned to the content column, not the viewport edge. Everything else on the site lives in
     a centred 30rem measure, and one element alone at the far right of a wide screen reads as
     something the browser added rather than something the page meant. On a phone the two are
     the same place. */
  left: 0;
  right: 0;
  width: 100%;
  max-width: 30rem;
  margin: 0 auto;
  padding: 0 var(--gutter);
  text-align: right;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  pointer-events: none;
}

.folio-number {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  margin-right: 0.15rem;
}

/*
 * The site footer.
 *
 * The line is set in the display serif and in the ink rather than the faint grey the rest of the
 * footer uses, because it is the only sentence on the page that says what the thing is for. A
 * manifesto whispered in 13px grey is a manifesto nobody reads.
 */
.site-foot {
  display: grid;
  gap: 1rem;
}

.site-foot-brand {
  display: inline-flex;
  text-decoration: none;
  width: fit-content;
  align-items: center;
  gap: 0.6rem;
}

.site-foot-brand .mark {
  width: 1.1rem;
  height: 1.1rem;
}

.site-foot-name {
  font-family: var(--font-ui);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.site-foot-line {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  line-height: 1.4;
  color: var(--ink);
  /* No max-width: the column is already capped at 30rem, and a second cap here squeezed the
     first sentence into a mid-phrase break. The <br> in the markup is the only break intended. */
}

/*
 * The contact code in the footer.
 *
 * A link as well as a code, because nobody can scan their own phone screen. The QR is for the
 * other case: someone at a desk, reaching for the phone in their pocket.
 */
.site-foot-qr {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: fit-content;
  padding: 0.6rem 0.85rem 0.6rem 0.6rem;
  border: 1px solid var(--rule);
  text-decoration: none;
  font-family: var(--font-ui);
  font-size: 0.8125rem;
  color: var(--ink);
}

.site-foot-qr img {
  display: block;
  /* The code is dark on transparent, so it needs its own light ground on any background. */
  background: #fff;
  padding: 0.25rem;
}

/*
 * The enlarged code.
 *
 * A native <dialog>, so Escape, focus handling and the backdrop come from the browser rather
 * than from us getting them subtly wrong. It exists to be photographed, so it is plain white
 * with room around it and nothing else competing.
 */
.qr-dialog {
  border: 1px solid var(--rule-strong);
  background: var(--paper);
  color: var(--ink);
  padding: 1.5rem;
  /* An explicit width, not just a max. A <dialog> is width: fit-content by default, which sizes
     itself against a child that is width: 100%, and the two settle far smaller than the space
     available. The code exists to be photographed, so it should use the room it has. */
  width: min(22rem, calc(100vw - 2rem));
}

.qr-dialog::backdrop {
  background: rgb(18 16 14 / 0.55);
}

.qr-dialog img {
  display: block;
  width: 100%;
  height: auto;
  background: #fff;
  padding: 0.75rem;
}

.qr-dialog-text {
  margin: 1rem 0 0;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  color: var(--ink);
}

.qr-dialog-actions {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.75rem;
  font-family: var(--font-ui);
  font-size: 0.8125rem;
}

.qr-dialog-actions button {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: underline;
}

/*
 * The source link.
 *
 * Sized and coloured like the brand line above it rather than like a button: it is provenance,
 * not a call to action, and the page already has one of those. The mark takes the faint ink so a
 * borrowed logo does not out-shout the site's own.
 */
.site-foot-src {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  text-decoration: none;
  font-family: var(--font-ui);
  font-size: 0.8125rem;
  color: var(--ink-faint);
}

.site-foot-src:hover {
  color: var(--ink);
}

.gh-mark {
  width: 1rem;
  height: 1rem;
  flex: none;
  fill: currentColor;
}

.site-foot-qr-meta {
  color: var(--ink-faint);
  font-size: 0.75rem;
}

/*
 * Footer navigation.
 *
 * Separators are drawn by CSS rather than typed into the markup, so the list can change without
 * anyone remembering to move a middle dot. The current page is not a link, because a link to
 * where you already are is a small lie.
 */
.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.5rem;
}

.nav > * + *::before {
  content: "·";
  margin-right: 0.5rem;
  color: var(--ink-faint);
}

.nav-here {
  color: var(--ink);
  font-weight: 600;
}

/* ---------- entrance choreography ---------- */

.reveal {
  opacity: 0;
  transform: translateY(0.9rem);
  animation: rise 0.75s var(--ease) forwards;
}

.reveal:nth-child(1) {
  animation-delay: 0.05s;
}

.reveal:nth-child(2) {
  animation-delay: 0.16s;
}

.reveal:nth-child(3) {
  animation-delay: 0.27s;
}

.reveal:nth-child(4) {
  animation-delay: 0.38s;
}

.reveal:nth-child(5) {
  animation-delay: 0.49s;
}

.reveal:nth-child(6) {
  animation-delay: 0.6s;
}

@keyframes rise {
  to {
    opacity: 1;
    transform: none;
  }
}

/* tap-to-reveal form panel (microsite) */
.panel {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.55s var(--ease), opacity 0.4s var(--ease);
}

.panel > div {
  overflow: hidden;
  min-height: 0;
  /* Containing block for absolutely positioned descendants (hidden radios, honeypot).
     Without this they escape the collapsed panel and add phantom page scroll. */
  position: relative;
}

.panel.open {
  grid-template-rows: 1fr;
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    animation: none;
  }

  .panel {
    transition: none;
  }

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

/* ---------- folded explainer, landing page ---------- */

.fold {
  border-top: 1px solid var(--rule);
}

.fold summary {
  list-style: none;
  cursor: pointer;
  padding: 1.1rem 0;
  font-size: 0.9375rem;
  color: var(--ink-faint);
  display: flex;
  align-items: center;
  gap: 0.6rem;
  transition: color 0.18s var(--ease);
}

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

.fold summary:hover {
  color: var(--accent);
}

.fold summary::after {
  content: "+";
  margin-left: auto;
  font-size: 1.125rem;
  line-height: 1;
}

.fold[open] summary::after {
  content: "−";
}

.fold[open] summary {
  color: var(--ink);
}

.fold-body {
  padding-bottom: 1.5rem;
}

/* ---------- responsive landing ---------- */

.landing-wrap {
  width: 100%;
  max-width: 30rem;
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.landing-main {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.landing-how {
  display: none;
}

.landing-privacy {
  border: 0;
  padding-top: 1rem;
}

.landing-footer {
  border: 0;
  padding-top: 0;
}

@media (min-width: 56rem) {
  .landing-wrap {
    max-width: 76rem;
  }

  .landing-main {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(20rem, 0.75fr);
    align-items: center;
    gap: clamp(5rem, 10vw, 10rem);
    padding-top: 5rem;
    padding-bottom: 4rem;
  }

  .landing-hero {
    max-width: 40rem;
  }

  .landing .statement {
    font-size: clamp(7rem, 11vw, 11rem);
  }

  .landing-hero .btn {
    width: auto;
    min-width: 18rem;
  }

  .landing-how {
    display: block;
    padding-left: clamp(2rem, 4vw, 4rem);
    border-left: 1px solid var(--rule-strong);
  }

  .landing-steps {
    list-style: none;
    padding: 0;
    margin: 2rem 0 0;
  }

  .landing-steps li {
    display: grid;
    grid-template-columns: 2rem 1fr;
    gap: 1rem;
    padding: 1.35rem 0;
    border-top: 1px solid var(--rule);
  }

  .landing-steps li:last-child {
    border-bottom: 1px solid var(--rule);
  }

  .landing-steps > li > span {
    color: var(--accent);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.1em;
  }

  .landing-steps strong {
    display: block;
    font-family: var(--font-display);
    font-size: 1.45rem;
    font-weight: 400;
    line-height: 1.15;
  }

  .landing-steps p {
    margin: 0.4rem 0 0;
    color: var(--ink-faint);
    font-size: 0.9rem;
    line-height: 1.45;
  }

  .landing-mobile-how {
    display: none;
  }

  .landing-bottom {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(20rem, 0.75fr);
    gap: clamp(5rem, 10vw, 10rem);
    align-items: start;
  }

  .landing-privacy,
  .landing-footer {
    border-top: 1px solid var(--rule);
    padding-top: 1.5rem;
  }

  .screen--folio .folio {
    max-width: 76rem;
  }

  .mode-cards,
  .choice-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .setup-wrap {
    max-width: 74rem;
  }

  .setup-wrap > .stack:not(.setup-grid) {
    max-width: 30rem;
  }

  .setup-grid {
    display: grid;
    grid-template-columns: minmax(18rem, 0.75fr) minmax(26rem, 1.25fr);
    grid-template-areas:
      "intro intro"
      "address address"
      "preview editor"
      "downloads downloads"
      "notice notice";
    gap: 3rem clamp(4rem, 8vw, 8rem);
    align-items: start;
  }

  .setup-grid > * + * {
    margin-top: 0;
  }

  .setup-intro {
    grid-area: intro;
    max-width: 38rem;
  }

  .setup-address {
    grid-area: address;
  }

  .setup-preview {
    grid-area: preview;
    position: sticky;
    top: 2rem;
  }

  .setup-editor {
    grid-area: editor;
  }

  .setup-downloads {
    grid-area: downloads;
    max-width: 44rem;
  }

  .setup-notice {
    grid-area: notice;
  }
}
