/* ===== Design tokens =====
   Every hue is sampled from the label logo. The wordmark blue (#0060A8) is the
   brand's loudest colour, so it now carries the structure: navy bands, links,
   focus rings. The wheat amber (#F09000) stays the single accent. The ground
   is cooled toward that blue rather than the warm cream it used to be: cream
   read as generic artisan-food styling and fought the logo's cool oval.
   Radius system: interactive elements 4px, media/containers 8px. */
:root {
  --bg: #F4F6F8;
  --surface: #E4EAF0;
  --surface-deep: #D3DDE7;
  --ink: #11263C;
  --ink-soft: #3B5670;
  --ink-muted: #52708C;
  --hairline: rgba(17, 38, 60, .14);
  --divider: rgba(17, 38, 60, .2);

  /* #0060A8 straight off the wordmark. It is only 5.99:1 on the ground, so the
     reversed-out bands use the deeper navies below, not the raw brand blue. */
  --blue: #0060A8;
  --navy: #0A3A61;
  --navy-deep: #06263F;

  /* Amber fills carry ink labels (6.4:1); amber text on light uses the deep
     tone (5.9:1). Bright amber never carries white text: that is 2.4:1. */
  --amber: #F09000;
  --amber-hover: #D9840F;
  --amber-deep: #8F4E06;
  --amber-on-navy: #F0A830;
  --on-amber: #11263C;
  /* Sampled from the logo and darkened until it cleared AA on the ground. */
  --error: #C4181B;
  --leaf: #2F7D4F;
  --on-navy: #E8F0F7;
  --on-navy-soft: rgba(232, 240, 247, .82);
  --on-navy-faint: rgba(232, 240, 247, .78);

  /* Paired on a contrast axis. Headings answer the logo's classical wordmark
     in Source Serif 4; UI and body run in Archivo, a workhorse grotesque with
     the accent coverage EN/FR/IT needs that holds up small, which is what a
     buyer scanning on a phone gets. The serif is a deliberate brand call: see
     the typography note in PRODUCT.md before swapping it out. */
  --display: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --ui: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --sans: var(--ui);

  /* Translucent tints. Every one of these used to be a hand-written rgba() at
     the point of use, which meant the same two hues re-derived by eye in nine
     places. Named by role, not by opacity, so a caller asks for "the scrim"
     rather than remembering that the scrim is 38%. */
  --ink-a14: rgba(17, 38, 60, .14);   /* = --hairline */
  --ink-a20: rgba(17, 38, 60, .2);    /* = --divider */
  --ink-a30: rgba(17, 38, 60, .3);    /* input borders */
  --ink-a40: rgba(17, 38, 60, .4);    /* outline-button border */
  --scrim: rgba(17, 38, 60, .38);     /* behind the mobile nav panel */
  --backdrop: rgba(17, 38, 60, .5);   /* behind the dialog */
  --bg-blur: rgba(244, 246, 248, .85);/* scrolled nav, under backdrop-filter */
  --on-navy-a22: rgba(232, 240, 247, .22); /* rules on navy */
  --on-navy-a28: rgba(232, 240, 247, .28); /* separators on navy */
  --focus-ring: rgba(0, 96, 168, .18);
  --focus-ring-error: rgba(196, 24, 27, .16);
  --field-bg: #FFFFFF; /* pure white: fields must read as holes in the tint */

  --radius-ui: 4px;
  --radius-box: 8px;
  --ease: cubic-bezier(.2, .7, .2, 1);

  /* Semantic z-index scale. Every layered element names its tier here rather
     than picking a number at the call site; the gaps leave room to insert one
     without renumbering. */
  --z-action-bar: 30;
  --z-nav: 40;
  --z-nav-panel: 50;
}

* { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* Stops iOS Safari inflating body copy when a phone is turned landscape. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Nothing on the page is meant to scroll sideways; this keeps a single
     over-wide element from turning the whole page into a horizontal pan.
     `clip`, not `hidden`: `hidden` would make the body a scroll container,
     which forces overflow-y to auto and breaks scrollIntoView on anchors. */
  overflow-x: clip;
}
/* The grey flash iOS paints over any tapped link or button. Every interactive
   element here already has its own :active state. */
a, button, [role="button"], summary { -webkit-tap-highlight-color: transparent; }

/* Anchor targets clear the sticky header instead of landing under it.
   --nav-h resolves to main.js's live measurement when it has one, and to the
   per-breakpoint constant below when it does not. The indirection matters:
   writing the measurement straight into --nav-h would put an inline value on
   <html> that outranks every media query here, so a single missed update would
   leave the offset wrong at every other breakpoint with no way back. This way
   the CSS fallback stays live for the whole session. */
:root { --nav-h: var(--nav-h-measured, 73px); }
#range, #craft, #contact { scroll-margin-top: calc(var(--nav-h) + 12px); }
h1, h2, h3, p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; display: block; }
button { font-family: inherit; cursor: pointer; }

.container {
  max-width: 1140px;
  margin-inline: auto;
  padding-inline: clamp(24px, 5vw, 56px);
}

/* ===== Photo slot =====
   Wrapper that crops its image to the slot. The tinted background shows only
   while the photo loads, or if it fails. */
.photo-slot {
  background: var(--surface);
  position: relative;
  overflow: hidden;
}
.photo-slot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute;
  inset: 0;
}

/* ===== Buttons ===== */
.btn {
  font-family: var(--ui);
  display: inline-block;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-ui);
  padding: 16px 32px;
  border: none;
  transition: background-color .2s ease, color .2s ease, border-color .2s ease, transform .2s var(--ease);
}
.btn:active { transform: translateY(0) scale(.98); }
/* 14px line box at 12.5px Archivo; 2x15 + 14 = 44px. The nav and action-bar
   CTA are primary actions and must not be the one control under target. */
.btn--sm { font-size: 12.5px; padding: 15px 20px; }
.btn--primary { background: var(--amber); color: var(--on-amber); }
.btn--outline { color: var(--ink); border: 1px solid var(--ink-a40); background: transparent; }

/* Hover effects are gated on a real pointer throughout the stylesheet. A touch
   device reports :hover on the last thing tapped and holds it there, so
   ungated rules leave a button stuck in its hover state after every tap. */
@media (hover: hover) and (pointer: fine) {
  .btn:hover { transform: translateY(-2px); }
  .btn--primary:hover { background: var(--amber-hover); }
  .btn--outline:hover { border-color: var(--ink); background: var(--ink); color: var(--bg); }
}

/* ===== Nav ===== */
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Fluid so the longest language still fits on one line just above the mobile
     breakpoint, where the bar is tightest. Italian is the binding case: at
     1025px the fixed 32px gaps left it ~30px short and it wrapped. */
  gap: clamp(16px, 2.4vw, 32px);
  padding: 14px clamp(24px, 4vw, 48px);
  border-bottom: 1px solid var(--hairline);
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  transition: background-color .35s ease, border-color .35s ease;
}
.nav.is-scrolled {
  background: var(--bg-blur);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  border-bottom-color: var(--divider);
}
/* The full oval carries the emblem and tagline, so it is unreadable at nav
   scale. The nav uses the flagged wordmark cropped from it; the oval runs in
   the footer. */
.nav__logo {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  flex-shrink: 0;
}
.nav__logo img { height: 22px; width: auto; }
.nav-links {
  font-family: var(--ui);
  display: flex;
  gap: clamp(18px, 2.2vw, 30px); /* overridden to 0 in the mobile panel */
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-soft);
}
.nav-links a {
  text-decoration: none;
  transition: color .2s ease;
  position: relative;
  padding-block: 14px; /* 16px line box + 2x14 = 44px, measured not assumed */
  white-space: nowrap; /* a nav label on two lines breaks the bar's alignment */
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 9px;
  height: 1.5px;
  background: var(--amber-deep);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .nav-links a:hover { color: var(--ink); }
  .nav-links a:hover::after { transform: scaleX(1); }
}

.nav-right { display: flex; align-items: center; gap: clamp(12px, 1.6vw, 24px); }
.nav-right .btn { white-space: nowrap; }
.lang-switch { display: flex; gap: 4px; }
.lang-switch button {
  font-family: var(--ui);
  background: none;
  border: none;
  min-width: 44px;
  min-height: 44px;
  padding: 5px 8px;
  border-radius: var(--radius-ui);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--ink-muted);
  transition: color .2s ease, background-color .2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .lang-switch button:hover { color: var(--ink); }
}
.lang-switch button[aria-current="true"] { color: var(--ink); background: var(--surface); font-weight: 600; }

/* ===== Mobile nav ===== */
.nav-toggle {
  display: none;
  background: none;
  border: none;
  padding: 8px;
  width: 44px;
  height: 44px;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  z-index: var(--z-nav-panel); /* above the panel's own stacking context */
}
.nav-toggle span {
  display: block;
  height: 2px;
  background: var(--ink);
  border-radius: 1px;
  transition: transform .3s var(--ease), opacity .2s ease;
}
/* Burger folds into a cross. The bars are 2px tall with a 5px gap, so the
   outer two travel 7px to meet in the middle. */
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(.4); }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* The panel hangs off the viewport under the sticky header rather than sitting
   in the document flow. In flow it scrolled away with the page, so opening the
   menu anywhere below the fold showed nothing at all. */
.nav-mobile-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 24px calc(28px + env(safe-area-inset-bottom));
  padding-inline: max(24px, env(safe-area-inset-left)) max(24px, env(safe-area-inset-right));
  border-bottom: 1px solid var(--hairline);
  background: var(--bg);
  position: absolute;
  top: 100%; /* the header's own height, whatever it currently is */
  left: 0;
  right: 0;
  max-height: calc(100dvh - var(--nav-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  visibility: hidden;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity .26s var(--ease), transform .26s var(--ease), visibility 0s .26s;
}
.nav-mobile-panel.is-open {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition: opacity .26s var(--ease), transform .26s var(--ease), visibility 0s;
}
.nav-mobile-panel .nav-links {
  flex-direction: column;
  gap: 0;
  font-size: 17px;
}
.nav-mobile-panel .nav-links a {
  padding-block: 16px;
  border-bottom: 1px solid var(--hairline);
}
.nav-mobile-panel .nav-links a::after { content: none; }
.nav-mobile-panel .nav-right {
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-top: 20px;
}
.nav-mobile-panel .btn { flex: 1; text-align: center; }

/* Scrim: dims the page behind the open panel and gives a tap-anywhere close. */
.nav-scrim {
  /* Absolute, not fixed: percentages on a fixed element resolve against the
     viewport, and this needs to start at the header's lower edge. It then
     runs a full viewport height, which always reaches the bottom of the
     screen because the header is pinned to the top. No z-index, because the panel
     follows it in source order and so paints above it. */
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 100dvh;
  background: var(--scrim);
  opacity: 0;
  visibility: hidden;
  transition: opacity .26s var(--ease), visibility 0s .26s;
}
.nav-scrim.is-open { opacity: 1; visibility: visible; transition: opacity .26s var(--ease), visibility 0s; }

/* Set on <body> while the panel is open, to stop the page scrolling behind.
   iOS Safari ignores `overflow: hidden` on the body, so the lock has to be a
   fixed position. That collapses the scroll offset, which main.js records and
   replays on close via the inline `top` it sets here. */
body.nav-open {
  position: fixed;
  width: 100%;
  overflow: hidden;
}
/* Taking the body out of flow also strands the sticky header: with no scroll
   port left, `sticky` resolves against the offset body and the nav rides off
   the top of the screen. Pinning it keeps the close button where it was. */
body.nav-open .nav { position: fixed; top: 0; left: 0; right: 0; }
/* ...but pinning it also takes it out of the body's flow, and it is the body's
   first child, so everything below would jump up by exactly the header's height
   the moment the menu opens. This gives that height back. Without it the page
   visibly scrolls up on open and back down on close. */
body.nav-open { padding-top: var(--nav-h); }

/* ===== Hero ===== */
.hero { padding-top: clamp(56px, 8vh, 88px); }
.hero__title {
  font-family: var(--display);
  font-size: clamp(44px, 7vw, 82px);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -.012em;
  max-width: 21ch;
  text-wrap: balance;
}
.hero__lede {
  margin-top: 26px;
  max-width: 54ch;
  font-size: 18px;
  line-height: 1.65;
  color: var(--ink-soft);
}
.hero__actions { display: flex; gap: 14px; margin-top: 36px; flex-wrap: wrap; }
.hero__media {
  margin-top: clamp(44px, 6vh, 64px);
  height: clamp(280px, 42vw, 460px);
  border-radius: var(--radius-box);
}

/* ===== Facts strip ===== */
.stats { padding: clamp(48px, 7vh, 72px) 0; }
.stats__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid var(--hairline);
  padding-top: clamp(36px, 5vh, 52px);
}
.stats__item + .stats__item { border-left: 1px solid var(--hairline); padding-left: 32px; }
.stats__item { padding-right: 24px; }
.stats__value {
  font-family: var(--display);
  font-size: clamp(28px, 3vw, 36px);
  font-weight: 700;
  letter-spacing: -.01em;
}
.stats__label {
  font-family: var(--ui); font-size: 14px; color: var(--ink-muted); margin-top: 6px; line-height: 1.4; }

/* ===== Range (menu) ===== */
.range { padding: clamp(64px, 10vh, 104px) 0; }
.range__title {
  font-family: var(--display);
  font-size: clamp(32px, 4.5vw, 50px);
  font-weight: 700;
  letter-spacing: -.01em;
  margin-bottom: clamp(40px, 6vh, 60px);
  max-width: 20ch;
}
.menu {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 34px clamp(48px, 7vw, 96px);
}
.menu-item { border-top: 1px solid var(--hairline); padding-top: 18px; }
/* The rule above puts a divider on top of every item, so the opening row gets a
   stray line hanging under the section title. Strip it from whatever starts the
   grid: two items across at this width, one once the grid collapses to a
   single column (restored in the max-width: 700px block). */
.menu-item:nth-child(-n+2) { border-top: none; padding-top: 0; }
.menu-item__name {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -.01em;
}
.menu-item__head { display: flex; align-items: baseline; gap: 8px; }
.menu-item__veg {
  color: var(--leaf);
  flex: none;
  transform: translateY(2px); /* optical: align the leaf body to the serif x-height */
}
.menu-item__ingredients { font-size: 15.5px; color: var(--ink-muted); margin-top: 5px; line-height: 1.5; }

/* ===== Craft ===== */
.craft { background: var(--surface); }
.craft__inner {
  padding-block: clamp(64px, 10vh, 104px);
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
.craft__media {
  border-radius: var(--radius-box);
  aspect-ratio: 4 / 5;
}
.craft__title {
  font-family: var(--display);
  font-size: clamp(32px, 4.5vw, 50px);
  font-weight: 700;
  letter-spacing: -.01em;
  max-width: 18ch;
}
.craft__body {
  margin-top: 28px;
  max-width: 60ch;
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink-soft);
}
/* Weight and space carry the emphasis; no accent stripe. */
.craft__pull {
  margin-top: 32px;
  padding-top: 28px;
  border-top: 1px solid var(--divider);
  max-width: 26ch;
  font-family: var(--display);
  font-size: clamp(22px, 2.6vw, 28px);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -.008em;
}

/* ===== Contact / CTA band ===== */
.cta-band {
  background: var(--navy);
  color: var(--on-navy);
}
.cta-band__content { padding-block: clamp(64px, 10vh, 104px); }
.cta-band__title {
  font-family: var(--display);
  font-size: clamp(34px, 5vw, 56px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.01em;
  max-width: 16ch;
  text-wrap: balance;
}
.cta-band__body {
  margin-top: 22px;
  max-width: 48ch;
  font-size: 17px;
  line-height: 1.65;
  color: var(--on-navy-soft);
}
.cta-band__content .btn { margin-top: 36px; }
.cta-band__contact {
  font-family: var(--ui);
  margin-top: 52px;
  padding-top: 28px;
  border-top: 1px solid var(--on-navy-a22);
  display: flex;
  align-items: center;
  gap: 28px;
  font-size: 14.5px;
  color: var(--on-navy-faint);
  flex-wrap: wrap;
}
.cta-band__sep { width: 1px; height: 15px; background: var(--on-navy-a28); }
.cta-band__contact a {
  text-decoration: none;
  transition: color .2s ease;
  padding-block: 14px; /* 16px line box + 2x14 = 44px, measured not assumed */
}
/* The glyph rides with the word rather than sitting apart from it, so the pair
   reads as one target. inline-flex, not flex, to keep it in the wrapping row. */
.cta-band__whatsapp {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
@media (hover: hover) and (pointer: fine) {
  .cta-band__contact a:hover { color: var(--on-navy); }
}

/* ===== Mobile action bar =====
   Only exists below 700px, where the nav bar has no room for the CTA beside the
   wordmark and the burger. `display: none` by default so it never renders on
   desktop even with the hidden attribute removed by script. */
.action-bar { display: none; }

@media (max-width: 700px) {
  .action-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-action-bar);
    padding: 10px max(16px, env(safe-area-inset-left)) calc(10px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-right));
    background: var(--bg-blur);
    -webkit-backdrop-filter: blur(14px) saturate(1.2);
    backdrop-filter: blur(14px) saturate(1.2);
    border-top: 1px solid var(--divider);
    transform: translateY(100%);
    transition: transform .3s var(--ease), visibility 0s .3s;
    visibility: hidden;
  }
  .action-bar.is-in {
    transform: none;
    visibility: visible;
    transition: transform .3s var(--ease), visibility 0s;
  }
  /* [hidden] must beat the flex above, or the bar renders before main.js has
     decided it should. */
  .action-bar[hidden] { display: none; }

  .action-bar .btn {
    flex: 1;
    text-align: center;
    /* Matches the 44px minimum the rest of the interface holds to. */
    padding-block: 15px;
  }
  .action-bar__icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    border-radius: var(--radius-ui);
    border: 1px solid var(--ink-a30);
    color: var(--ink);
    text-decoration: none;
  }
  .action-bar__icon:active { background: var(--surface); }
  /* WhatsApp's own green, which is how the mark is recognised. It is the one
     colour on the page that is not sampled from the logo, and it earns the
     exception by being a third-party identity rather than brand decoration.
     4.6:1 on the bar's ground, so it clears AA as a large-ish glyph. */
  .action-bar__icon--whatsapp { color: #1D7A44; }
}

/* ===== Footer ===== */
.footer {
  font-family: var(--ui);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 26px clamp(24px, 4vw, 48px);
  background: var(--navy-deep);
  color: var(--on-navy-faint);
  font-size: 13px;
  flex-wrap: wrap;
}
.footer__logo { height: 86px; width: auto; flex-shrink: 0; }

/* ===== Modal ===== */
dialog#inquiry-modal {
  width: min(520px, calc(100vw - 48px));
  /* The form is taller than a phone screen once the keyboard is up. Capping
     the dialog and scrolling inside it keeps the submit button reachable
     instead of clipped off the bottom with no way to scroll to it. */
  max-height: 88dvh;
  overflow: hidden;
  border: none;
  border-radius: var(--radius-box);
  padding: 0;
  background: var(--bg);
  color: var(--ink);
}
dialog#inquiry-modal::backdrop { background: var(--backdrop); }
.modal__inner {
  padding: 40px 40px 36px;
  position: relative;
  max-height: 88dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.modal__close {
  position: absolute;
  top: 8px;
  right: 8px;
  background: none;
  border: none;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-muted);
  /* 44px target; the glyph itself is far smaller than the tappable area. */
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  z-index: 1;
}
@media (hover: hover) and (pointer: fine) {
  .modal__close:hover { color: var(--ink); }
}
.modal__title { font-family: var(--display); font-size: 27px; font-weight: 700; letter-spacing: -.01em; margin-bottom: 8px; }
.modal__subtitle { font-size: 14.5px; color: var(--ink-soft); line-height: 1.6; margin-bottom: 28px; }

.form-field { margin-bottom: 16px; }
.form-field label {
  font-family: var(--ui);
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
.form-field input,
.form-field select,
.form-field textarea {
  width: 100%;
  font: inherit;
  font-size: 14.5px;
  color: var(--ink);
  padding: 11px 12px;
  border: 1px solid var(--ink-a30);
  border-radius: var(--radius-ui);
  background: var(--field-bg);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--navy);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* The asterisk on a required label. aria-hidden in the markup: `required` and
   aria-required already carry the state to a screen reader, so this is a
   sighted-only cue and must not be read out as part of the label. */
.form-field__req {
  color: var(--error);
  margin-left: 3px;
  font-weight: 700;
}
/* Sits under the last field, in front of the network-error slot, so it reads
   as a note on the form rather than as a message about it. */
.form-legend {
  font-family: var(--ui);
  font-size: 12.5px;
  color: var(--ink-muted);
  margin: -4px 0 18px;
}

/* Inline validation. Injected by main.js directly after the offending field so
   the message sits inside the same .form-field block and travels with it when
   .form-row collapses to one column. */
.field-error {
  font-family: var(--ui);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--error);
  margin: 6px 0 0;
}
.form-field [aria-invalid="true"] { border-color: var(--error); }
/* Error state must survive focus, or the border reverts to navy the moment the
   buyer tabs into the field they were just sent to fix. */
.form-field [aria-invalid="true"]:focus {
  border-color: var(--error);
  box-shadow: 0 0 0 3px var(--focus-ring-error);
}

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
.form-error {
  display: none;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--error);
  margin: 0 0 16px;
}
.form-error.is-visible { display: block; }
.form-actions { margin-top: 24px; }
.form-actions .btn { width: 100%; text-align: center; border: none; }
.form-actions .btn[disabled] { opacity: .6; cursor: default; }

.success-view { display: none; text-align: center; padding: 12px 0 8px; }
.success-view.is-visible { display: block; }
.success-view__icon {
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--navy); color: var(--on-navy);
  display: grid; place-items: center; margin: 0 auto 20px;
  font-size: 22px;
}
.success-view__title { font-family: var(--display); font-size: 24px; font-weight: 700; margin-bottom: 10px; }
.success-view__body { font-size: 14.5px; color: var(--ink-soft); line-height: 1.6; }
#inquiry-form.is-hidden { display: none; }

/* ===== Responsive ===== */
/* Above the mobile breakpoint the panel and scrim must never render, whatever
   state JS left them in on the way up from a narrow window. */
@media (min-width: 1025px) {
  .nav-mobile-panel, .nav-scrim { display: none; }
}

/* The wordmark is the widest fixed item in the bar (it never shrinks), so it
   buys back the most room in the narrow desktop band where the longest
   language would otherwise run out of it. */
@media (min-width: 1025px) and (max-width: 1140px) {
  .nav__logo img { height: 20px; }
}

@media (max-width: 1024px) {
  /* Child combinator: the panel's own copies live outside .nav and must stay. */
  .nav > .nav-links,
  .nav > .nav-right { display: none; }
  .nav-toggle { display: flex; }
}

@media (max-width: 860px) {
  .craft__inner { grid-template-columns: 1fr; gap: 40px; }
  .craft__media { aspect-ratio: 16 / 10; }
}

@media (max-width: 700px) {
  /* Trims the header from 73px to 65px, which is a meaningful slice of a
     phone screen to hand back to the content under a sticky bar. Kept in step
     with the --nav-h that drives scroll-margin-top. */
  :root { --nav-h: var(--nav-h-measured, 65px); }
  .nav { padding-block: 10px; }
  .nav__logo { min-height: 40px; }
  .nav__logo img { height: 17px; }

  .container { padding-inline: max(22px, env(safe-area-inset-left)) max(22px, env(safe-area-inset-right)); }

  .hero { padding-top: 40px; }
  .hero__title { font-size: clamp(35px, 9.5vw, 46px); }
  .hero__lede { margin-top: 20px; font-size: 16.5px; }
  .hero__actions { flex-direction: column; align-items: stretch; margin-top: 28px; }
  .hero__actions .btn { text-align: center; }
  .hero__media { margin-top: 36px; height: 260px; }

  .stats { padding: 44px 0; }
  .stats__grid { grid-template-columns: 1fr 1fr; gap: 26px 0; padding-top: 32px; }
  .stats__item { padding-right: 16px; }
  .stats__item + .stats__item { border-left: none; padding-left: 0; }
  .stats__item:nth-child(even) { border-left: 1px solid var(--hairline); padding-left: 20px; }

  .range { padding: 56px 0; }
  .range__title { margin-bottom: 32px; }
  .menu { grid-template-columns: 1fr; gap: 22px; }
  /* Single column now, so only the very first item opens the grid. */
  .menu-item:nth-child(2) { border-top: 1px solid var(--hairline); padding-top: 18px; }

  .craft__inner { padding-block: 56px; gap: 32px; }
  .craft__body { margin-top: 20px; }
  .craft__pull { margin-top: 26px; padding-top: 22px; max-width: none; }

  .cta-band__content { padding-block: 56px; }
  .cta-band__content .btn { display: block; text-align: center; margin-top: 28px; }
  .cta-band__contact { flex-direction: column; align-items: flex-start; gap: 4px; margin-top: 36px; }
  .cta-band__sep { display: none; }

  .footer {
    flex-direction: column;
    text-align: center;
    padding-bottom: calc(26px + env(safe-area-inset-bottom));
  }
  .footer__logo { height: 68px; }

  .form-row { grid-template-columns: 1fr; }
  .modal__inner { padding: 32px 22px calc(28px + env(safe-area-inset-bottom)); }

  /* Mobile Safari zooms the whole page in whenever a focused field is under
     16px. 16px inputs are the only reliable way to prevent that; the label
     scale above them is unchanged, so the form still reads as designed. */
  .form-field input,
  .form-field select,
  .form-field textarea {
    font-size: 16px;
    padding: 13px 12px;
  }

  /* Full-width sheet anchored to the bottom of the screen: the thumb is near
     the bottom, and it stays put when the keyboard pushes the viewport up. */
  dialog#inquiry-modal {
    width: 100%;
    max-width: 100%;
    max-height: 92dvh;
    margin: 0 0 0 auto;
    top: auto;
    bottom: 0;
    border-radius: var(--radius-box) var(--radius-box) 0 0;
  }
  .modal__inner { max-height: 92dvh; }
}

/* Small phones (iPhone SE and down) where the hero was running edge to edge. */
@media (max-width: 380px) {
  .hero__title { font-size: 33px; }
  .btn { padding: 15px 22px; letter-spacing: .06em; }
  .stats__value { font-size: 26px; }
  .menu-item__name { font-size: 20px; }
  /* The language switcher and the CTA no longer both fit on one row here, and
     the CTA is nowrap, so stack them rather than let the row overflow. */
  .nav-mobile-panel .nav-right { flex-direction: column; align-items: stretch; gap: 12px; }
  .nav-mobile-panel .lang-switch { justify-content: center; }
}

/* Landscape phones: vertical space is the scarce axis, so the vh-based
   rhythm has to come down or the hero alone fills the screen. */
@media (max-height: 500px) and (orientation: landscape) {
  .hero { padding-top: 28px; }
  .hero__media { height: 200px; }
  .nav-mobile-panel { gap: 4px; }
  .nav-mobile-panel .nav-links a { padding-block: 11px; }
}

/* ===== Motion & focus ===== */
::selection { background: var(--amber); color: var(--on-amber); }

a:focus-visible,
button:focus-visible,
.btn:focus-visible,
.lang-switch button:focus-visible {
  outline: 2px solid var(--amber-deep);
  outline-offset: 3px;
  border-radius: var(--radius-ui);
}
.cta-band a:focus-visible,
.cta-band .btn:focus-visible,
.footer a:focus-visible {
  outline-color: var(--on-navy);
}

@keyframes kdp-rise {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}
.hero__title   { animation: kdp-rise .9s  .05s both var(--ease); }
.hero__lede    { animation: kdp-rise .9s  .16s both var(--ease); }
.hero__actions { animation: kdp-rise .9s  .28s both var(--ease); }
.hero__media   { animation: kdp-rise 1s   .4s  both var(--ease); }

/* Toggled by the IntersectionObserver in main.js */
.reveal { opacity: 0; transform: translateY(24px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }

dialog#inquiry-modal[open] { animation: kdp-modal-in .38s var(--ease); }
@keyframes kdp-modal-in {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
/* The sheet rises from the bottom edge it is anchored to, rather than doing
   the desktop dialog's small centred lift. Declared after the base rule above,
   not in the responsive block, because that block precedes it in the cascade
   and an equal-specificity override there would lose. */
@keyframes kdp-sheet-in {
  from { opacity: 0; transform: translateY(100%); }
  to   { opacity: 1; transform: none; }
}
@media (max-width: 700px) {
  dialog#inquiry-modal[open] { animation-name: kdp-sheet-in; }
}
dialog#inquiry-modal[open]::backdrop { animation: kdp-fade .35s ease both; }
@keyframes kdp-fade { from { opacity: 0; } to { opacity: 1; } }

@keyframes kdp-pop {
  from { transform: scale(.85); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
.success-view.is-visible .success-view__icon { animation: kdp-pop .4s var(--ease) both; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero__title, .hero__lede, .hero__actions, .hero__media,
  dialog#inquiry-modal[open], .success-view.is-visible .success-view__icon {
    animation: none;
  }
  .reveal { opacity: 1; transform: none; transition: none; }
  .btn:hover { transform: none; }
  .nav-toggle span { transition: none; }
  /* Visibility keeps its zero-duration delay so the panel still leaves the
     accessibility tree when closed; only the movement is dropped. */
  .nav-mobile-panel { transform: none; transition: visibility 0s .01s; }
  .nav-mobile-panel.is-open { transition: visibility 0s; }
  .nav-scrim { transition: visibility 0s .01s; }
  .nav-scrim.is-open { transition: visibility 0s; }
  /* Same treatment: the bar still appears and disappears, it just stops
     sliding. transform must be cleared or it stays parked off-screen. */
  .action-bar { transform: none; transition: visibility 0s .01s; }
  .action-bar.is-in { transition: visibility 0s; }
}

/* Honeypot: off-screen rather than display:none, which some bots skip. It is
   also aria-hidden and tabindex="-1" in the markup, so nothing reaches it by
   keyboard or screen reader. */
.form-honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
