/* ============================================================
   UPLIFT LAYER
   Loaded AFTER site.css and media.css, so it wins on the few
   properties it deliberately restates.

   What this is: the shared rigour. A spacing rhythm, a real type
   scale, focus and press states, and the base state that lets
   Motion drive the reveals. What it is NOT: a look. Every colour
   and every typeface still comes from the site's own site.css,
   because thirty-eight shops are meant to look like thirty-eight
   shops.

   Per-site tuning happens through --u-rise and --u-dur, set in
   each site's own stylesheet against its MOTION dial.
   ============================================================ */

:root {
  /* ---- Spacing, 4px rhythm ----
     Taken from the `wired` token set: 2/4/8/12/16/20/24/32/48.
     A fixed rhythm is the difference between a page that was laid
     out and a page that accumulated margins. */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.25rem;  --s-6: 1.5rem;   --s-8: 2rem;     --s-10: 2.5rem;
  --s-12: 3rem;    --s-16: 4rem;    --s-20: 5rem;    --s-24: 6rem;

  /* ---- Type scale ----
     Fluid, roughly a minor third at the small end opening toward a
     perfect fourth for display sizes. Each step is a clamp so the
     page never needs a breakpoint just to resize text. */
  --t-xs:   clamp(0.75rem, 0.72rem + 0.12vw, 0.82rem);
  --t-sm:   clamp(0.86rem, 0.83rem + 0.15vw, 0.94rem);
  --t-base: clamp(1rem,    0.97rem + 0.16vw, 1.06rem);
  --t-lg:   clamp(1.15rem, 1.08rem + 0.32vw, 1.35rem);
  --t-xl:   clamp(1.4rem,  1.26rem + 0.60vw, 1.8rem);
  --t-2xl:  clamp(1.7rem,  1.45rem + 1.10vw, 2.4rem);
  --t-3xl:  clamp(2.1rem,  1.60rem + 2.10vw, 3.4rem);

  /* Motion defaults; each site overrides against its dial. */
  --u-rise: 18px;
  --u-dur: 0.62s;
}

/* ---- Headings ----
   text-wrap: balance stops a heading dropping one orphaned word
   onto its own line, which is the single most common way a
   carefully set headline looks accidental. It is ignored by
   browsers that do not support it, so there is no fallback to
   write. CJK benefits as much as Latin here. */
h1, h2, h3 { text-wrap: balance; }
p, li, dd { text-wrap: pretty; }

/* ---- Anchors ----
   Every in-page link lands under a fixed header without this. */
[id] { scroll-margin-top: calc(var(--nav-h, 66px) + var(--s-4)); }

/* ---- Numbers that sit in columns ----
   Prices, times, capacities and the booking reference. Proportional
   digits make a column of prices look ragged; tabular figures are
   what a menu or a ledger is set in. */
.price, .price-hold, .figure, .cap, .hours dd, .charge-rows .k,
.menu-row .price, .floors .cap, .floors-total b, .br-ref b,
time, .num { font-variant-numeric: tabular-nums; }

/* ---- Interaction ----
   The guidelines ask for a visible response to hover AND focus, and
   for the focused state to be at least as prominent as the hovered
   one. Pointer-only devices get the hover; everyone gets the focus. */
.btn, a, button, summary, [role="button"] { touch-action: manipulation; }

@media (hover: hover) {
  .btn:hover { filter: brightness(1.04); }
}
.btn:active { transform: translateY(1px); }

/* A single focus treatment for the whole page, stronger than hover,
   and never removed without replacement. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}

/* ---- Cards and tiles ----
   A small lift, transform and shadow only, so it composites. The
   shadow is tinted with the page's own ink rather than pure black,
   which on a warm or coloured ground reads as dirt. */
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .m-figure, .cast-card, .menu-row, .info-list li {
    transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1);
  }
  .m-even .m-figure:hover,
  .m-gallery .m-figure:hover,
  .cast-card:hover { transform: translateY(-3px); }
}

/* ---- Reveal base ----
   Motion owns the animation, so the CSS transition is switched off
   the moment we know Motion is driving. Without JS, .u-motion is
   never set, the CSS transition below runs, and media.js's 4-second
   failsafe adds .in regardless: the page is readable either way.

   32-mon reached this pass with eleven .rv elements and NO .rv rule
   at all, so its reveals did nothing. Declaring the base here fixes
   that site and standardises the other seven. */
.rv {
  opacity: 0;
  transform: translateY(var(--u-rise));
  transition: opacity var(--u-dur) cubic-bezier(0.16, 1, 0.3, 1),
              transform var(--u-dur) cubic-bezier(0.16, 1, 0.3, 1);
}
.rv.in { opacity: 1; transform: none; }

/* Motion is animating; do not run a second, competing transition. */
html.u-motion .rv { transition: none; }

/* The one rule that must never be conditional: if the reader asked
   for less motion, there is no motion and nothing starts hidden. */
@media (prefers-reduced-motion: reduce) {
  .rv, html.u-motion .rv {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .btn:active { transform: none; }
}

/* ---- Layout safety ----
   A stray wide child is the usual cause of a horizontal scrollbar on
   a phone, and it is always a bug rather than a decision. */
body { overflow-x: hidden; }
.wrap > * { min-width: 0; }

/* Full-bleed sections must clear a notch. */
.hero, footer { padding-left: env(safe-area-inset-left);
                padding-right: env(safe-area-inset-right); }
