/* Design system layer.
   Loaded AFTER site.css, so it refines rather than replaces.

   WHY A LAYER AND NOT A REWRITE. Each of these sites was hand-built and its
   hero type was measured at 390px, with comments in the markup recording line
   counts that were checked rather than guessed. Blanket-overriding those
   clamps would silently undo measured work. So this file introduces the token
   scale, fixes what is genuinely ad-hoc, and adds the interaction polish that
   was missing everywhere. It does not touch a measured hero size.

   Every site keeps its own --accent and its own Japanese display face. Nothing
   here sets a colour or a typeface; it sets rhythm, states and motion.

   Per-site dials arrive as --ds-lift and --ds-dur, written by the build step
   from the taste-skill MOTION dial. A calmer shop gets a smaller lift and a
   slower settle without a different stylesheet. */

:root {
  /* Spacing. The ratio is the discipline, not the numbers: each step is a
     clear jump from the last, so a reader perceives grouping rather than a
     smear of near-identical gaps. Modelled on Apple's scale, which is the one
     reference in the library built for content rather than dashboards. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;
  --s8: 4.5rem;
  --s9: 6.5rem;

  /* Fluid type for the SUPPORTING scale only. Hero sizes stay where the site
     put them. These cover the sizes that were previously scattered one-offs. */
  --step--1: clamp(0.78rem, 0.76rem + 0.12vw, 0.85rem);
  --step-0:  clamp(0.95rem, 0.92rem + 0.16vw, 1.05rem);
  --step-1:  clamp(1.08rem, 1.02rem + 0.3vw, 1.25rem);
  --step-2:  clamp(1.25rem, 1.15rem + 0.5vw, 1.6rem);
  --step-3:  clamp(1.5rem, 1.32rem + 0.9vw, 2.1rem);

  --ds-ring: 2px;
  --ds-lift: 2px;          /* overridden per site from the MOTION dial */
  --ds-dur: 0.30s;
  --ds-ease: cubic-bezier(0.22, 0.75, 0.3, 1);
}

/* ---------- Typography polish ----------
   Cheap, universal, and the difference between "a page" and "typeset". */

h1, h2, h3, .hero h1, .sec-head h2 {
  /* Stops a heading leaving one orphaned word on its own line. CJK ignores it
     harmlessly, Latin headings in the en and es pages benefit. */
  text-wrap: balance;
}

p, li, dd, figcaption {
  text-wrap: pretty;
}

/* Anything that is a column of figures must line up. Prices, hours, seat
   counts, booking references, telephone numbers. Proportional digits in a
   price list read as sloppy even when nobody can say why. */
.price, .figure, .charge-rows, .rd-ref-code, .fact, time,
[class*="price"], [class*="hours"], [class*="tel"] {
  font-variant-numeric: tabular-nums;
}

/* ---------- Focus ----------
   The existing rule was a plain outline. This keeps the outline (so it works
   in forced-colours mode, where box-shadow is dropped) and adds a soft halo
   so the ring stays visible against a photograph. */
:focus-visible {
  outline: var(--ds-ring) solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
@supports (color: color-mix(in srgb, red 50%, white)) {
  :focus-visible {
    box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 28%, transparent);
  }
}

/* A focused control must never sit under the sticky header. */
[id], h2, h3, section {
  scroll-margin-top: calc(var(--nav-h, 68px) + var(--s5));
}

/* ---------- Touch and pointer hygiene ---------- */
a, button, input, select, textarea, [role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* ---------- Interaction states ----------
   transform and opacity only, so these stay on the compositor. Properties are
   always listed explicitly: the catch-all keyword animates things nobody
   intended, including ones that force layout on every frame. */
@media (prefers-reduced-motion: no-preference) {
  .btn,
  .m-gallery button,
  .nav-cta {
    transition:
      transform var(--ds-dur) var(--ds-ease),
      box-shadow var(--ds-dur) var(--ds-ease),
      background-color var(--ds-dur) var(--ds-ease),
      border-color var(--ds-dur) var(--ds-ease),
      color var(--ds-dur) var(--ds-ease);
  }

  .btn:hover,
  .nav-cta:hover {
    transform: translateY(calc(var(--ds-lift) * -1));
  }

  /* A press must feel like the surface gave way. Without this a tap on a
     phone produces no feedback at all until the page changes. */
  .btn:active,
  .nav-cta:active,
  .m-gallery button:active {
    transform: translateY(1px) scale(0.994);
  }

  /* Gallery tiles settle rather than jump. The image scales inside its own
     clipped frame, so neighbours never move: no layout is touched. */
  .m-gallery button .m-figure,
  .m-gallery button .m-photo {
    transition: transform 0.5s var(--ds-ease);
    will-change: transform;
  }
  .m-gallery button:hover .m-photo,
  .m-gallery button:focus-visible .m-photo {
    transform: scale(1.04);
  }
}

/* Interactive states must gain contrast, not just move. Movement alone is
   invisible to anyone who cannot perceive it. */
.btn:hover,
.nav-cta:hover {
  border-color: var(--accent);
}

/* ---------- Content handling ----------
   Long user-supplied or translated strings must not blow a layout out. The
   Spanish pages routinely run 30% longer than the Japanese. */
.btn, .nav-cta, .label, .k, h1, h2, h3 {
  overflow-wrap: break-word;
}
.field, .rd-detail div, .info-grid > * {
  min-width: 0;
}

/* ---------- Motion handoff ----------
   When motion.js is driving reveals it sets .ds-motion on <html> and takes
   ownership of .rv, so the CSS transition must stand down or the two fight
   over the same property. If the script never runs, this rule never applies
   and the original CSS reveal is still in charge. */
html.ds-motion .rv {
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  .m-gallery button .m-figure,
  .m-gallery button .m-photo { transition: none; }
}
