/* ==========================================================================
   Hiraya Dental Group — components
   The horizon device, buttons, cards, FAQ blocks, form controls.
   Source: CLAUDE.md §7. No component library — eight pages do not need one.
   No strings live in this file.
   ========================================================================== */

/* --- The horizon device ---------------------------------------------------
   A single brass rule. The section divider, and THE ONLY transition device
   (§7). No other separator, flourish, or transition is permitted.
   -------------------------------------------------------------------------- */

.horizon {
  border: 0;
  height: var(--rule-weight);
  background: var(--rule);
  margin: 0;
}

.horizon--short {
  width: var(--space-6);   /* 64px — an accent mark, not a full divider */
}

/* --- Buttons --------------------------------------------------------------
   Minimum 44px tall. Never full-width on desktop (§7).

   ✅ SETTLED 2026-08-13 by Raymund: CHARCOAL label on a BRASS fill.
   Full history and reasoning at .btn--primary below. Brass is the surface,
   never the lettering.

   ⚠ SUPERSEDED, kept so the reversal is legible: this block previously read
   "RESOLVED 2026-08-10 — brass label on a charcoal fill (Option B)", which was
   itself overturned the same day. Brass lettering is closed, not pending.
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-3);
  font-size: var(--size-body);
  font-weight: var(--weight-medium);
  line-height: 1.2;
  text-decoration: none;
  border: var(--rule-weight) solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.btn:hover { text-decoration: none; }

/* Primary — CHARCOAL label on a BRASS fill.
   ✅ SETTLED 2026-08-13 by Raymund, asked directly and answered "dark text on
   brass". This closes the open row that three earlier passes left hanging.

   THE HISTORY, because the file has said three different things:
     · 18 §11.5, as written      — brass label on charcoal
     · 2026-08-10, first ruling  — brass label on charcoal ("Option B")
     · 2026-08-10, same day      — changed to IVORY on charcoal by owner
                                    instruction, on the correct ground that
                                    Decision R makes brass DECORATIVE ONLY and
                                    a button label is text
     · 09's recorded interim     — "charcoal text on a brass fill"
     · 2026-08-13, SETTLED       — charcoal text on a brass fill. This one.

   The owner's answer matches 09's interim and satisfies Decision R without
   straining it: the BRASS IS THE SURFACE, which is decorative use, and the
   LABEL IS CHARCOAL, which is the rule for text. Nothing here licenses brass
   lettering — that idea is now closed, not merely superseded.

   Measured 5.29:1 — passes WCAG AA for normal text, not merely large text.
   ⚠ The ratio is NOT the justification and must never be cited as one. Brass
   lettering on charcoal measures the same 5.29:1 and was still wrong. Passing
   a contrast threshold is not permission to break a brand rule; the two tests
   are independent.

   Brass remains prohibited as body text, headings, links and labels, and on
   any pale ground. Do not extend this by analogy: it settles the primary
   button fill and nothing else. */
.btn--primary {
  background: var(--brass);
  color: var(--charcoal);
  border-color: var(--brass);
}

/* Hover inverts to the charcoal fill, mirroring .btn--secondary:hover below
   rather than inventing a new device. It is the only perceptible hover
   available: Decision R forbids a darker brass variant, so the fill cannot
   simply deepen the way the old charcoal button's did. Contrast rises from
   5.29:1 to 12.86:1. */
.btn--primary:hover { background: var(--charcoal); color: var(--ivory); border-color: var(--charcoal); }

/* Secondary — charcoal outline. */
.btn--secondary {
  background: transparent;
  color: var(--charcoal);
  border-color: var(--charcoal);
}

.btn--secondary:hover { background: var(--charcoal); color: var(--ivory); }

.btn:disabled,
.btn[aria-disabled="true"] {
  background: var(--stone);
  border-color: var(--stone);
  color: var(--charcoal);
  opacity: 0.55;
  cursor: not-allowed;
}

@media (min-width: 768px) {
  .btn { width: auto; }   /* never full-width on desktop */
}

/* --- Cards ----------------------------------------------------------------
   White on ivory, 1px stone border, NO shadow (§7).
   -------------------------------------------------------------------------- */

.card {
  background: var(--bg-raised);
  border: var(--rule-weight) solid var(--border-subtle);
  border-radius: var(--radius);
  padding: var(--space-3);
}

@media (min-width: 768px) {
  .card { padding: var(--space-4); }
}

.card > * + * { margin-top: var(--space-2); }

/* --- FAQ ------------------------------------------------------------------
   ALL ANSWERS VISIBLE BY DEFAULT. No accordion — it hides text from
   extraction engines and from hurried readers (§7).
   -------------------------------------------------------------------------- */

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

.faq-item > * + * { margin-top: var(--space-1); }

.faq-item h3 { font-size: var(--size-h3); }

/* --- Empty slots ----------------------------------------------------------
   Structure is built before strings are registered (§9). A slot renders as a
   visible placeholder in development so an unfilled slot cannot be mistaken
   for finished work. This class must not survive into production.
   -------------------------------------------------------------------------- */

.slot--empty {
  display: inline-block;
  min-width: var(--space-6);
  min-height: 1em;
  border-bottom: 1px dashed var(--stone);
}

/* --- Form controls --------------------------------------------------------
   Structure only. No microcopy — those strings are DRAFT (§9 step 5).
   -------------------------------------------------------------------------- */

.field > * + * { margin-top: var(--space-1); }

.input {
  width: 100%;
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-2);
  background: var(--white);
  color: var(--charcoal);
  border: var(--rule-weight) solid var(--charcoal);
  border-radius: var(--radius);
}

.input::placeholder { color: var(--charcoal); opacity: 0.5; }

.input:disabled { background: var(--stone); opacity: 0.55; }

/* Errors are charcoal text with an icon. No red — there is no error colour
   in this system (§7). */
.field-error {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1);
  font-size: var(--size-small);
  color: var(--charcoal);
  font-weight: var(--weight-medium);
}

.field-error svg { flex: none; width: 1em; height: 1em; margin-top: 0.25em; }

/* --- Checkbox — required for the signup consent tick-box (approved) -------- */

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1);
  cursor: pointer;
}

.checkbox input {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  margin-top: 0.25em;
  accent-color: var(--charcoal);
}

/* --- Header and footer shells --------------------------------------------- */

.site-header {
  border-bottom: var(--rule-weight) solid var(--border-subtle);
  padding-block: var(--space-2);
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

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

.nav a { text-decoration: none; font-size: var(--size-small); }

.nav a:hover,
.nav a[aria-current="page"] { text-decoration: underline; }

.site-footer {
  background: var(--bg-inverse);
  color: var(--text-inverse);
  padding-block: var(--space-5);
}

.site-footer a { color: var(--text-inverse); }

.breadcrumb {
  font-size: var(--size-small);
  display: flex;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.breadcrumb a { text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }

/* ── Empty asset slot ──────────────────────────────────────────────────
   An asset that does not exist yet. 18 §15: mark it, never fill it with a
   stock image or an icon.

   ⚠ THE HEIGHT CAP IS THE LOAD-BEARING PART, and it is a spec requirement,
   not taste. An uncapped 16:9 placeholder is ~56vw tall and swallows the
   whole first screen. 18 §10.1 lists what the first screen carries — logo,
   h1, one subhead line, the CTA slot — "and nothing else above the fold."
   A placeholder for an image nobody has taken is not on that list, and
   15 §3.8's whole fallback position is that the page must work
   typographically with no photography at all.

   Ratio is expressed but bounded: the cap wins, so an absent asset reads as
   a reserved band rather than a broken page. When a real image lands it
   replaces the slot entirely and the cap goes with it. */
.asset-slot {
  display: block;
  width: 100%;
  max-height: min(34vh, 300px);
  border: 1px dashed var(--stone);
  border-radius: var(--radius);
}
.asset-slot--16x9 { aspect-ratio: 16 / 9; }
.asset-slot--4x5  { aspect-ratio: 4 / 5;  max-width: 280px; }
.asset-slot--1x1  { aspect-ratio: 1 / 1;  max-width: 220px; }

/* ── Header must hold one row, phone included ──────────────────────────
   Found during the 2026-08-10 acceptance pass: on a 375px screen the five
   header slots wrapped into THREE rows and took ~300px of an 812px screen,
   with the brand mark stranded on the second row.

   Cause: an empty nav slot inherits .slot--empty's min-width, which is sized
   for prose, not for a menu item.

   Why it matters beyond looks: 18 §10.1 fixes what the first screen carries —
   logo, h1, one subhead line, the CTA slot — "and nothing else above the
   fold." A three-row nav block pushed the headline off the phone entirely.

   ⚠ STILL NOT FULLY CONFORMANT, AND IT CANNOT BE FIXED HERE.
   §10.1 also excludes "navigation beyond a menu control" from the first
   screen, so the phone header should collapse to a single menu control. That
   control needs an accessible name, and every navigation label on this site
   is DRAFT — PENDING REGISTRATION. Inventing one would be a developer writing
   a public string, which §15 prohibits. The pattern goes in with the labels,
   in one pass. */
.site-header .nav { flex-wrap: nowrap; }
.site-header .nav .slot--empty { min-width: var(--space-4); }

@media (max-width: 640px) {
  .site-header .container { gap: var(--space-2); }
  .site-header .nav { gap: var(--space-2); }
  .site-header .nav .slot--empty { min-width: 24px; }
  .brand .slot--empty { width: 84px !important; }
}

/* ── Tap targets ──────────────────────────────────────────────────────
   18 §11: "Minimum 44 × 44 px with 8 px clearance. Applies to the nav, the
   form checkbox, and every link in the footer."

   Measured 26 px tall on every page during the 2026-08-10 acceptance pass —
   14 failing targets per page. Height is fixed here; the links keep their
   visual position because the box grows around the text, not the type. */
.nav a,
.breadcrumb a,
.site-footer a,
.brand {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
}

/* 8 px clearance minimum between adjacent targets. --space-2 is 16px. */
.nav { gap: var(--space-2); row-gap: var(--space-1); }

/* The consent control: the whole label is the target, so it must carry the
   height rather than the 1.15em box alone. */
.checkbox { min-height: var(--tap-min); }

/* ⚠ THE 44 px *WIDTH* HALF OF THIS RULE IS NOT MET IN THE HEADER, AND
   CANNOT BE MET AS THE HEADER IS CURRENTLY BUILT.
   Five targets at 44 px wide plus 8 px clearance needs 252 px of a 375 px
   screen before the logo. That arithmetic is exactly why 18 §10.1 excludes
   "navigation beyond a menu control" from the phone's first screen — the
   spec expects a menu control here, not five links.

   That control needs an accessible name, and every navigation label on this
   site is DRAFT — PENDING REGISTRATION. A developer inventing one is an
   unapproved public string (§15). So the width half of §11, the menu-control
   half of §10.1, and the unnamed-link accessibility failure are all ONE
   blocker with ONE fix: register the navigation labels.
   Recorded here so the next builder does not re-derive it. */

/* Placeholder links — a link whose label is not yet registered still has to
   be a legal touch target. Scoped with :has() to links that contain ONLY an
   empty slot, so real text links in prose keep normal inline flow. */
a:has(> .slot--empty) {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
}
/* Breadcrumb links are wayfinding, not prose, so the WCAG inline-link
   exception does not cover them. "Home" measured 42 x 44 — two pixels short. */
.breadcrumb a { min-width: var(--tap-min); justify-content: flex-start; }
.breadcrumb .slot--empty { min-width: var(--tap-min); }

/* ── Form measure ─────────────────────────────────────────────────────
   Found on desktop during the 2026-08-10 acceptance pass: the form and every
   input rendered 1184 px wide while the prose beside them was 720 px. A
   single-line email field spanning the full page is hard to scan, breaks the
   column the page has just established, and reads as unfinished.

   18 §11 caps line length at 60–75 characters and the type system already
   expresses that as --text-max. A form is read on the same measure as the
   text that introduces it. */
#opening-interest { max-width: var(--text-max); }

/* ── The horizon rule needs air ────────────────────────────────────────
   .horizon is the site's ONE transition device (§11). It shipped with zero
   vertical margin, so on /opening-updates it sat flush between the last line
   of body copy and the first form label — the two blocks read as collided
   rather than separated, which is the opposite of what the device is for.

   Set here rather than inline so every instance behaves the same; the footer
   instances already carried their own inline margin and are unaffected. */
main > .horizon,
main .horizon { margin-block: var(--space-5); }
main .horizon--short { margin-block: var(--space-4); }

/* ── Mobile navigation control ─────────────────────────────────────────
   18 §10.1 excludes "navigation beyond a menu control" from the phone's
   first screen. Built 2026-08-10, once 07 v1.14 registered "Menu" as the
   accessible name of an icon-only control — before that, building this would
   have meant inventing a public string.

   Trigger: with the approved labels in place, five text links measured
   438–446 px against a 375 px viewport. Horizontal overflow, not a judgement
   call.

   .js-nav is set by nav.js, so with JavaScript off the links stay visible
   and usable rather than being hidden by a stylesheet with nothing to
   reveal them. */
.nav-toggle { display: none; }

@media (max-width: 640px) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--tap-min);
    min-height: var(--tap-min);
    padding: 0;
    background: none;
    border: var(--rule-weight) solid var(--border-subtle);
    border-radius: var(--radius);
    color: var(--charcoal);
    cursor: pointer;
  }

  /* Three bars, drawn rather than shipped as an icon font or an SVG file. */
  .nav-toggle__bars,
  .nav-toggle__bars::before,
  .nav-toggle__bars::after {
    display: block;
    width: 18px;
    height: 2px;
    background: currentColor;
  }
  .nav-toggle__bars { position: relative; }
  .nav-toggle__bars::before,
  .nav-toggle__bars::after { content: ""; position: absolute; left: 0; }
  .nav-toggle__bars::before { top: -6px; }
  .nav-toggle__bars::after  { top: 6px; }

  .js-nav .site-header .nav { display: none; }

  .js-nav .site-header .nav[data-open] {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    z-index: 10;
    background: var(--bg-raised);
    border-block: var(--rule-weight) solid var(--border-subtle);
    padding: var(--space-2) var(--space-3);
  }

  /* Full-width rows clear 44 × 44 comfortably, which five inline links on a
     375 px screen never could. */
  .js-nav .site-header .nav[data-open] a {
    min-height: var(--tap-min);
    width: 100%;
  }

  .site-header { position: relative; }
}

/* A standalone navigation link sitting in its own paragraph is a target, not
   an inline link inside a sentence, so the WCAG inline exception does not
   cover it. Measured 21 px tall on the homepage provider preview. */
main p > a:only-child {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
}

/* Footer navigation on a phone. 18 §11 applies the 44 × 44 minimum to "every
   link in the footer", and seven inline links measured 42 px wide. Stacked
   full-width rows clear it and are easier to hit besides. */
@media (max-width: 640px) {
  .site-footer .nav {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  .site-footer .nav a { width: 100%; min-height: var(--tap-min); }
}

/* ── Logo ──────────────────────────────────────────────────────────────
   Horizon H horizontal lockup. Approved production SVG, placed 2026-08-10.
   Header: full colour on ivory. Footer: reversed one-colour on charcoal,
   per 18 §2.9.

   Sized by HEIGHT so the 2.5:1 lockup keeps its approved proportions at any
   width — 01 requires spacing and proportions to be preserved. width/height
   attributes on the img reserve the space so nothing shifts as it loads. */
/* Sized up from 34px on 2026-08-10 after looking at it: the lockup carries a
   "DENTAL GROUP" sub-line under the wordmark, and at 34px tall that line
   rendered around 3px and turned to mush. 44px costs nothing in the header —
   the nav links are already 44px tall, so the header height is unchanged. */
.brand img { display: block; height: 44px; width: auto; }

@media (max-width: 640px) {
  /* 18 §10.1: "Logo — Horizon H, small" is the first thing on the phone.
     Small, but not so small the sub-line becomes a smudge.

     If this still reads as cramped once the real header is reviewed on a
     phone, the package's own README sanctions the alternative: "Icon only —
     use when the brand name is already present or space is limited." That is
     a brand-presentation choice, so it is flagged rather than taken. */
  .brand img { height: 34px; }
}

.brand--footer { display: inline-flex; margin-bottom: var(--space-3); }
.brand--footer img { height: 40px; }
