/* ==========================================================================
   components.css — shared component structure, driven by theme tokens.
   Deliberately avoids the generic-template tells: no boxed icon-card grid,
   no tracked-caps eyebrow on every section, no decorative side-stripes.
   ========================================================================== */

/* --- Header / nav --------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line);
}
.header-inner { display: flex; align-items: center; gap: var(--gap); flex-wrap: wrap; padding-block: 0.85rem; }
.brand { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; color: var(--navy); }
.brand-mark { flex: 0 0 auto; }
.brand-name { font-family: var(--font-display); font-size: 1.02rem; font-weight: 600; letter-spacing: var(--tracking-display); }

.main-nav { margin-left: auto; }
.main-nav ul, .lang-switcher ul, .footer-nav ul { list-style: none; display: flex; gap: 1.4rem; margin: 0; padding: 0; flex-wrap: wrap; }
.main-nav a {
  text-decoration: none; color: var(--body); font-size: 0.95rem;
  padding: 0.4rem 0; position: relative;
}
.main-nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: -2px; height: 2px;
  background: var(--accent); transition: right 0.28s var(--ease);
}
.main-nav a:hover { color: var(--navy); }
.main-nav a:hover::after, .main-nav a[aria-current="page"]::after { right: 0; }
.main-nav a[aria-current="page"] { color: var(--navy); }

.lang-switcher { border-left: 1px solid var(--line); padding-left: 1.2rem; }
.lang-switcher a { text-decoration: none; font-size: var(--fs-sm); color: var(--muted); }
.lang-switcher a:hover { color: var(--navy); }
.lang-switcher a.is-active { color: var(--navy); font-weight: 700; }

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-block; padding: 0.8em 1.7em; border-radius: var(--radius);
  font-weight: 600; font-size: 0.98rem; text-decoration: none;
  border: 1.5px solid transparent; letter-spacing: 0.01em;
  transition: background-color 0.24s var(--ease), color 0.24s var(--ease),
              border-color 0.24s var(--ease), transform 0.24s var(--ease);
}
.btn-primary { background: var(--action); color: var(--action-ink); }
.btn-primary:hover { background: var(--action-hover); color: var(--action-ink); }
.btn-ghost { border-color: var(--navy); color: var(--navy); }
.btn-ghost:hover { background: var(--navy); color: #fff; }
/* Enlarged CTA — the primary enquiry button carries more weight. */
.btn-lg { padding: 1.05em 2.4em; font-size: 1.08rem; border-radius: calc(var(--radius) + 2px); }
.btn-primary.btn-lg { box-shadow: 0 8px 22px color-mix(in srgb, var(--action) 38%, transparent); }
.btn-primary.btn-lg:hover { transform: translateY(-1px); box-shadow: 0 12px 30px color-mix(in srgb, var(--action) 46%, transparent); }
/* Light button — the contrast partner to the brass primary on dark grounds
   (hero, navy CTA): a solid cream fill with navy text, not an outline. */
.btn-light { background: var(--hero-ink); color: var(--navy); border-color: var(--hero-ink); }
.btn-light:hover { background: #fff; color: var(--navy); border-color: #fff; }

/* --- Hero (full-bleed photograph + navy scrim) ---------------------------- */
.hero {
  position: relative; isolation: isolate; overflow: hidden;
  color: var(--hero-ink); background: #0b1428;
}
.hero-photo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 62% 42%; z-index: 0;
}
/* Navy scrim so the serif headline reads over the blue-hour city. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--hero-scrim); pointer-events: none;
}
.hero .container { position: relative; z-index: 2; }
.hero-inner {
  padding-block: clamp(4.5rem, 3rem + 9vw, 9rem) clamp(3rem, 2rem + 5vw, 5.5rem);
  max-width: 54rem;
}
.hero-heading {
  font-family: var(--font-display);
  color: var(--hero-ink); font-size: var(--fs-hero); line-height: 1.06;
  letter-spacing: var(--tracking-display); max-width: none; margin: 0 0 0.6em;
  text-wrap: balance; font-weight: 600;
  text-shadow: 0 1px 30px rgba(6, 12, 26, 0.35);
}
/* The sub-headline breaks at its own commas into poised, deliberate lines: the
   breaks are real newlines stored in the copy JSON, rendered via
   `[data-e]{white-space:pre-line}` (base.css). Give it room to keep each clause
   intact. */
.hero-sub {
  font-size: var(--fs-lg); color: var(--hero-sub);
  max-width: 54ch; line-height: 1.7;
}
.hero-actions { display: flex; gap: 0.9rem; flex-wrap: wrap; margin-top: 2.2rem; }
.hero .btn-ghost { border-color: color-mix(in srgb, var(--hero-ink) 60%, transparent); color: var(--hero-ink); }
.hero .btn-ghost:hover { background: var(--hero-ink); color: var(--navy); border-color: var(--hero-ink); }

/* Composed entrance — not scroll-gated, renders correctly headless. */
@media (prefers-reduced-motion: no-preference) {
  .hero-heading, .hero-sub, .hero-actions {
    animation: rise 0.8s var(--ease) both;
  }
  .hero-heading { animation-delay: 0.07s; }
  .hero-sub { animation-delay: 0.15s; }
  .hero-actions { animation-delay: 0.23s; }
  .hero-photo { animation: heroZoom 1.4s var(--ease) both; }
}
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
@keyframes heroZoom { from { opacity: 0; transform: scale(1.06); } to { opacity: 1; transform: scale(1); } }

/* The hero's enquiry button jumps to the closing contact block, and the "view
   our fees" CTA (plus the old /fees.html redirect) lands on #fees. Keep both
   targets clear of the sticky header when they scroll into view. */
#contact, #fees { scroll-margin-top: 5.5rem; }

/* --- Highlights (editorial columns, not boxed icon-cards) ----------------- */
.card-grid {
  list-style: none; margin: 2.4rem 0 0; padding: 0;
  display: grid; gap: calc(var(--gap) * 1.6) calc(var(--gap) * 1.4);
  grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
}
.card { padding-top: 1.4rem; border-top: 2px solid var(--navy); }
.card h3 { font-family: var(--font-display); color: var(--navy); margin: 0 0 0.55rem; font-weight: 600; }
.card p { color: var(--body); margin: 0; }

/* --- Services ------------------------------------------------------------- */
.service { padding-top: 1.6rem; border-top: 1px solid var(--line); margin-bottom: 3rem; }
.service:first-of-type { border-top: 0; padding-top: 0; }
.service > h2 { color: var(--navy); }

.ticks { list-style: none; padding: 0; margin: 1.2rem 0; }
.ticks li { position: relative; padding-left: 1.7rem; margin-bottom: 0.6rem; }
.ticks li::before { content: "✓"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }

.service-points { list-style: none; padding: 0; margin: 1.4rem 0 0; display: grid; gap: 1.2rem; }
.service-points li { position: relative; padding-left: 1.8rem; }
.service-points li::before {
  content: ""; position: absolute; left: 0; top: 0.55em; width: 0.7rem; height: 1.5px;
  background: var(--accent);
}
.service-point-label { display: block; font-family: var(--font-display); font-weight: 600; color: var(--navy); margin-bottom: 0.15rem; }
.service-point-desc { display: block; color: var(--body); font-size: 0.97em; }

/* Response-time: a filled tint callout with a leading marker — no side-stripe. */
.response-time {
  display: flex; align-items: baseline; gap: 0.7rem;
  font-weight: 600; color: var(--navy); font-family: var(--font-display);
  margin-top: 1.8rem; padding: 1rem 1.2rem;
  background: var(--tint); border: 1px solid var(--line); border-radius: var(--radius);
}
.response-time::before { content: "→"; color: var(--accent); font-weight: 700; flex: 0 0 auto; }

/* Section heading with the brass hairline flourish (used instead of an
   eyebrow stamped over every section). */
.rule-heading { position: relative; padding-top: 1.15rem; }
.rule-heading::before { content: ""; position: absolute; top: 0; left: 0; width: 2.6rem; height: 2px; background: var(--accent); }

/* The process lead reads full and even — wider than the default narrow .lead,
   so its lines fill more than half the block and break comfortably. */
.lead.process-intro { max-width: 44rem; text-wrap: pretty; }

/* --- Process (numbered sequence — numbers earn their place here) ---------- */
.process-list {
  list-style: none; margin: 2.6rem 0 0; padding: 0;
  display: grid; gap: 2.2rem var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.process-step { position: relative; padding-top: 1.5rem; border-top: 1px solid var(--line-strong); }
.process-num {
  font-family: var(--font-display); font-size: 0.98rem; font-weight: 600;
  color: var(--accent-strong); letter-spacing: 0.06em;
  display: inline-block; margin-bottom: 0.7rem;
}
.process-num::before { content: ""; }
.process-step h3 { font-family: var(--font-display); color: var(--navy); font-weight: 600; margin: 0 0 0.45rem; }
.process-step p { margin: 0; color: var(--body); }
/* A step's qualifying footnote (e.g. the in-person catchment area) — quieter
   than the step body, but still comfortably above the 4.5:1 floor. */
.step-note { margin: 0.7rem 0 0; font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; }

/* --- Plan comparison (Services) ------------------------------------------- */
/* Two plans, one either/or decision — a side-by-side panel pair, not a
   repeated card grid. Panels sit on the raised cream so they read as two
   choices lifted off the band behind them. */
.plan-grid {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  margin-top: 2.4rem;
}
.plan {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: clamp(1.5rem, 1rem + 1.6vw, 2.2rem);
  box-shadow: var(--shadow);
}
.plan h3 {
  position: relative; padding-bottom: 0.9rem; margin: 0 0 1.2rem;
  border-bottom: 1px solid var(--line-strong);
  font-size: 1.28rem; font-weight: 600;
}
.plan .ticks { margin: 0; }
.plan .ticks li:last-child { margin-bottom: 0; }

/* --- Notes / important-notice list ---------------------------------------- */
/* Numbered because the office refers to these items by number in
   correspondence — the order carries information. */
.notes-list {
  margin: 2rem 0 0; padding: 0; list-style: none;
  counter-reset: notes; max-width: 62em;
  display: grid; gap: 1.1rem;
}
.notes-list li {
  counter-increment: notes; position: relative;
  padding-left: 2.6rem; color: var(--body);
}
.notes-list li::before {
  content: counter(notes); position: absolute; left: 0; top: 0.1em;
  width: 1.75rem; height: 1.75rem; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: 0.85rem; font-weight: 600;
  color: var(--accent-ink); background: var(--accent);
}

/* --- CTA band ------------------------------------------------------------- */
.cta-band { text-align: center; }
.cta-band p { font-size: var(--fs-lg); font-family: var(--font-display); color: var(--ink); margin-bottom: 1.4rem; max-width: 40ch; margin-inline: auto; }

/* Navy CTA band — the one deliberate block of navy on the cream page. */
.cta-navy {
  position: relative; isolation: isolate; overflow: hidden;
  background:
    linear-gradient(120deg, rgba(11, 20, 40, 0.94), rgba(16, 30, 58, 0.86)),
    var(--navy);
  color: var(--hero-ink); border-radius: var(--radius-lg);
  padding: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);
  text-align: center; box-shadow: var(--shadow-lift);
}
.cta-navy .eyebrow { justify-content: center; color: var(--hero-eyebrow); }
/* No leading dash on the closing contact label — just the word. */
.cta-navy .eyebrow::before { display: none; }
/* The invitation title is an editable field: `nowrap` here would outrank
   `[data-e]{white-space:pre-line}` and silently swallow any line break added in
   the visual editor — and a longer edited title could not wrap at all, spilling
   out of this `overflow:hidden` card. Balance the lines instead of forbidding
   them; the current short strings still sit on one line. */
.cta-navy h2 { color: var(--hero-ink); max-width: none; margin-inline: auto; text-wrap: balance; }
.cta-navy p { color: var(--hero-sub); max-width: 54ch; margin-inline: auto; margin-bottom: 1.8rem; font-size: var(--fs-lg); }
.cta-navy .btn-ghost { border-color: color-mix(in srgb, var(--hero-ink) 60%, transparent); color: var(--hero-ink); }
.cta-navy .btn-ghost:hover { background: var(--hero-ink); color: var(--navy); }
.cta-actions { display: flex; gap: 0.9rem; flex-wrap: wrap; justify-content: center; }

/* 24-hour reply promise — the closing reassurance beneath the CTA buttons.
   Higher specificity than `.cta-navy p` so it keeps its own smaller scale. */
.cta-navy .cta-promise {
  margin: 1.9rem auto 0; max-width: 48ch;
  display: flex; flex-wrap: wrap; gap: 0.5rem 0.85rem;
  align-items: baseline; justify-content: center;
  font-size: var(--fs-sm); color: var(--hero-sub); line-height: 1.6;
}
/* The badge is an editable field, so it must not declare `white-space` at all:
   any value here ties with `[data-e]{white-space:pre-line}` on specificity and
   wins on order, silently discarding line breaks added in the visual editor.
   The pill holds one line on its own — the label is a few characters, and the
   flex parent already gives it its intrinsic width. */
.cta-promise-badge {
  font-family: var(--font-display); font-weight: 600; color: var(--hero-ink);
  border: 1px solid color-mix(in srgb, var(--hero-eyebrow) 60%, transparent);
  border-radius: 999px; padding: 0.24rem 0.8rem;
}
.cta-promise-line { flex: 1 1 18rem; min-width: 0; text-align: center; }

/* --- Profile -------------------------------------------------------------- */
.profile-grid { display: grid; gap: var(--space); grid-template-columns: 1fr; }
@media (min-width: 800px) { .profile-grid { grid-template-columns: 1.8fr 1fr; } }
.profile-card { background: var(--tint); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.6rem; align-self: start; }
.profile-photo { margin: 0 0 1.3rem; border-radius: var(--radius); overflow: hidden; aspect-ratio: 4 / 5; background: var(--band); }
/* The portrait is 2:3 and the frame is 4:5, so `cover` has to crop vertically.
   Bias the crop upward — centred would clip the top of the head. */
.profile-photo img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 18%; }
.info-list { display: grid; grid-template-columns: auto 1fr; gap: 0.55rem 1.2rem; margin: 0; }
.info-list dt { font-family: var(--font-display); font-weight: 600; color: var(--navy); }
.info-list dd { margin: 0; }
.office-address { font-style: normal; }

/* --- Tables --------------------------------------------------------------- */
.table-wrap { overflow-x: auto; margin: 1rem 0 2.4rem; }

/* --- Fee schedule ---------------------------------------------------------
   The office's fee table, and the one place a solid navy fill appears on an
   otherwise cream page. It reads as a document laid on the band: raised cream
   panel, hairline border, the single ambient shadow — the same material as
   `.card` and `.plan`, because that is what it is.

   Structure: one <tbody> per procedure, opened by a full-width `.fee-group`
   row. That keeps the data rows to three columns (category + two plans), which
   is what makes the phone layout below a clean stack rather than a sideways
   scroll — the amounts are the whole point of the page and must never be
   parked off-screen. */
.fee-doc {
  margin-top: 2rem; max-width: 62rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: var(--shadow);
}
.fee-doc .table-wrap { margin: 0; }
.fee-doc-actions { margin: 1.6rem 0 0; }

/* `fixed` rather than the default `auto`, for two reasons. Auto layout treats a
   cell width as a negotiable hint and re-derives the columns from content, so a
   width dragged in the visual editor was silently discarded — under `fixed` the
   header row's widths ARE the columns, which is what makes an override stick.
   It also stops the very long English category labels from bullying the amount
   columns narrower than their own figures. */
.fee-table {
  width: 100%; border-collapse: collapse; font-size: var(--fs-base);
  table-layout: fixed;
}
/* Wide enough for the longest amount ("200,000 日圓") plus cell padding without
   wrapping. The category column declares no width and so takes all the rest. */
.fee-table thead th.fee-amount { width: 10.5rem; }
.fee-table th, .fee-table td {
  text-align: left; padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--line); vertical-align: top;
}
.fee-table thead th {
  background: var(--navy); color: #fff;
  font-family: var(--font-display); font-weight: 600; letter-spacing: 0.01em;
  border-bottom: 0; vertical-align: bottom;
}
/* Procedure band. Tint against the panel's raised cream, so it separates the
   groups without becoming a second header row competing with the navy one. */
.fee-group th {
  background: var(--tint); color: var(--navy);
  font-family: var(--font-display); font-weight: 600;
  border-bottom: 1px solid var(--line-strong);
  padding-block: 0.7rem;
}
tbody + tbody .fee-group th { border-top: 1px solid var(--line-strong); }
/* Category labels run long in English (three status names with their Japanese
   terms), so 500 rather than 600 — bold across four wrapped lines reads as
   shouting, and the row's real emphasis belongs on the amount. */
.fee-table tbody th { font-weight: 500; color: var(--ink); line-height: 1.6; }
.fee-table tbody tr:last-child > * { border-bottom: 0; }

/* Amounts: right-aligned and tabular so the digits stack into a column the eye
   can compare down. Their column width lives on the header cell above (see
   `table-layout: fixed`), so the category column takes whatever is left. The
   headings are free to wrap; the amounts are not. `white-space` is declared on an editable
   [data-e] cell deliberately here, unlike everywhere else in this file: an
   amount is one token, and a break inside "JPY 100,000" is never intended. */
.fee-amount { text-align: right; font-variant-numeric: tabular-nums; }
.fee-table tbody .fee-amount {
  white-space: nowrap; font-weight: 600; color: var(--navy);
}

@media (prefers-reduced-motion: no-preference) {
  .fee-table tbody tr { transition: background 0.18s var(--ease); }
}
.fee-table tbody tr:not(.fee-group):hover { background: var(--tint); }

/* Phone: the three columns become a stacked block per category — the label on
   its own line, then the two plans side by side, which is the comparison the
   reader came for. The <thead> is hidden and its wording carried down by
   `data-label` on each amount, so no column loses its name. */
@media (max-width: 46rem) {
  .fee-table thead {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; clip-path: inset(50%);
    overflow: hidden; white-space: nowrap;
  }
  .fee-table, .fee-table tbody, .fee-table tr, .fee-table th, .fee-table td { display: block; }
  .fee-table tbody tr:not(.fee-group) {
    display: grid; grid-template-columns: 1fr 1fr;
    column-gap: 1.1rem; padding: 0.95rem 1.1rem 1.05rem;
    border-bottom: 1px solid var(--line);
  }
  .fee-table tbody tr:not(.fee-group) > * { padding: 0; border-bottom: 0; }
  .fee-table tbody tr:not(.fee-group) th { grid-column: 1 / -1; margin-bottom: 0.75rem; }
  /* Permanent residence and naturalisation have no sub-category, so their row
     label is deliberately blank. Without this the empty cell still claims a
     grid row and its margin, leaving a dead gap above the amounts. */
  .fee-table tbody tr:not(.fee-group) th:empty { display: none; }
  .fee-amount { text-align: left; width: auto; }
  .fee-amount::before {
    content: attr(data-label); display: block;
    font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 400;
    color: var(--muted); line-height: 1.45; white-space: normal;
    margin-bottom: 0.15rem;
  }
}

/* --- Contact form embed --------------------------------------------------- */
/* --- Booking panel (Contact) ----------------------------------------------
   Microsoft Bookings cannot be embedded (it serves X-Frame-Options), so the
   consultation calendar is a hand-off rather than an iframe. This panel has to
   do what the embed would have: say plainly what the appointment is, remove
   the doubt about what happens on the far side of the click, and leave a way
   through for anyone who would rather not use a calendar at all. */
.booking-panel {
  max-width: 46em;
  padding: clamp(1.5rem, 1rem + 2.2vw, 2.75rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 2px solid var(--navy);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.booking-panel h2 { margin-top: 0; }
.booking-body {
  font-family: var(--font-display); font-size: var(--fs-lg);
  color: var(--ink); line-height: 1.62; max-width: 42ch; margin-bottom: 0;
  text-wrap: pretty;
}

.booking-actions { margin: 1.9rem 0 0; }
/* Outbound marker. The link's aria-label carries the same cue in words, so the
   meaning is never left to the glyph alone. */
.btn-external::after { content: "↗"; margin-left: 0.5em; }

.booking-phone {
  margin: 1.7rem 0 0; padding-top: 1.35rem;
  border-top: 1px solid var(--line);
  color: var(--body); font-size: 0.95rem;
}
.booking-phone a {
  font-family: var(--font-display); font-weight: 600;
  color: var(--accent-strong); white-space: nowrap;
}

@media (max-width: 30rem) {
  .booking-actions .btn-lg { display: block; text-align: center; }
}

/* --- Contact row: booking panel + messaging QR panel -----------------------
   The codes are a second route to the same office, not a footnote to the
   booking panel, so they sit BESIDE it as an equal-height sibling rather than
   in a band underneath. Flex, not grid: this is one row that wraps, and the
   wrap is the whole responsive story. */
.contact-row {
  display: flex; flex-wrap: wrap; align-items: stretch;
  gap: var(--gap);
}
/* The panel keeps its own 46em measure; it just no longer owns the full row. */
.contact-row .booking-panel { flex: 1 1 32rem; }

/* One panel holding all three codes — same box treatment as .plan on Services,
   so the two panels in this row read as a matched pair. The assets are already
   identical 600×600 squares (see contact.njk), so ONE width governs all three
   and there are no per-channel rules to drift apart. */
.qr-panel {
  --qr-size: clamp(6rem, 22vw, 8rem);
  list-style: none; margin: 0;
  flex: 0 1 auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: clamp(1.4rem, 1rem + 1.4vw, 2rem);
  box-shadow: var(--shadow);
  display: flex; flex-wrap: wrap; justify-content: center; gap: 1.4rem;
}
/* Stacked layout (narrow, panel sitting under the booking panel): the three
   codes read left-to-right with the channel name beneath each. */
.qr-item { display: flex; flex-direction: column; align-items: center; gap: 0.55rem; }
/* No plate and no padding: each file is cropped to its module square, and the
   panel's own white ground is what supplies the quiet zone around it. A fixed
   width (not a stretched aspect-ratio box) is deliberate — deriving the square
   from the row height makes the code's width depend on the panel's height while
   the panel's width depends on the code, and that circularity is what made the
   codes size inconsistently between languages, whose labels differ in width. */
.qr-code { display: block; width: var(--qr-size); height: auto; }
.qr-label {
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-sm);
  line-height: 1.3; color: var(--navy); text-align: center;
}

/* Beside the booking panel: one vertical stack. The panel stretches to the
   booking panel's height and `space-between` distributes the three rows down
   it, so the box matches without the codes themselves having to resize. */
@media (min-width: 62rem) {
  .qr-panel {
    --qr-size: clamp(6.5rem, 9vw, 8.5rem);
    flex-direction: column; flex-wrap: nowrap; justify-content: space-between; gap: 1.5rem;
  }
  .qr-item { flex-direction: row; align-items: center; gap: 1rem; }
  .qr-label { text-align: left; }
}

/* --- Page head (interior pages) ------------------------------------------- */
.page-head { background: var(--tint); border-bottom: 1px solid var(--line); }
.page-head h1 { position: relative; padding-top: 1.1rem; }
.page-head h1::before { content: ""; position: absolute; top: 0; left: 0; width: 3rem; height: 2px; background: var(--accent); }
.page-head .lead { margin-bottom: 0; }

/* --- Footer --------------------------------------------------------------- */
.site-footer { background: var(--footer-bg); color: var(--footer-ink); margin-top: 0; }
.footer-inner { display: grid; gap: var(--gap); grid-template-columns: 1fr; padding-block: var(--space); }
@media (min-width: 720px) { .footer-inner { grid-template-columns: 1.6fr 1fr 1fr; } }
.site-footer h2, .footer-name { color: #fff; }
.footer-name { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; margin-bottom: 0.4rem; }
.footer-reg { font-size: var(--fs-sm); color: color-mix(in srgb, var(--footer-ink) 78%, transparent); }
.footer-nav ul { flex-direction: column; gap: 0.55rem; }
.site-footer a { color: var(--footer-ink); text-decoration: none; }
.site-footer a:hover { color: var(--footer-hover); }
.footer-contact p { margin: 0 0 0.4rem; }
.footer-legal { border-top: 1px solid color-mix(in srgb, var(--footer-ink) 22%, transparent); padding-block: 1.2rem; }
.footer-legal p { margin: 0; font-size: var(--fs-sm); color: color-mix(in srgb, var(--footer-ink) 78%, transparent); }
