@import url("fonts.css");

/* ─────────────  brand tokens (from asiahub.de)  ───────────── */
:root{
  /* ── Brand ──────────────────────────────────────────────────────────────────
     The three logo colours, unchanged. Sampled from the wordmark's opaque
     pixels: 65.9% #F4932A orange, 34.1% #749D3E green, and --char is the
     charcoal plate the wordmark sat on before its background was made
     transparent. Orange leads because the logo and the dining room both lead
     with it; green supports; charcoal is the ink and the footer ground, which
     is how the brand asset itself uses it.
     These three are FILLS and INK. They are never small text -- see below. */
  --orange:#F4932A;
  --green:#749D3E;
  --char:#3E3E3F;

  /* Text-safe variants of those same two hues. The logo values measure 2.19:1
     (orange) and 2.99:1 (green) against --bg: perfectly good as a fill with
     dark text on top, unreadable as 11-13px lettering. Darkened until they
     clear 4.5:1. Measured in the browser, not estimated. */
  /* The split is by JOB, not by taste, so it stays consistent as pages are added:
       orange = action and attention -- CTAs, page kickers, headlines, the offer
       green  = information and provenance -- prices, day labels, dividers, badges
     The wordmark is 65.9% orange to 34.1% green, and this keeps roughly that ratio. */
  --orange-ink:#A3621C;             /* 4.59:1 on --bg -- leading accent as text */
  --green-ink:#5C7C31;              /* 4.52:1 on --bg -- supporting accent      */

  /* Display type only -- 24px and up, where AA asks for 3:1 rather than 4.5:1.
     Holding the big headlines to the small-text pair made them read brown; these
     are the same hues at the lightness the actual threshold allows. Using them on
     anything under 24px is a bug: they measure 3.25:1. */
  --orange-disp:#D0720B;            /* 3.25:1 on --bg */
  --green-disp:#6F963B;             /* 3.25:1 on --bg */

  /* Bright variants. Legible ONLY on a dark ground -- the charcoal footer band
     and the hero photograph. On --bg they measure 1.93:1 and 1.79:1, so putting
     either on a light surface is always a bug. */
  --orange-lift:#F5A957;            /* 5.44:1 on --char */
  --green-lift:#ACCC62;             /* 5.88:1 on --char */

  /* ── Neutrals ───────────────────────────────────────────────────────────────
     Named by role, not by colour, so the palette can move without every rule
     that references it becoming a lie. --fg is the brand charcoal.

     There is deliberately no --fg-dim. It was mid-grey rgb(88,88,88) and carried
     nearly every paragraph on the site, which is what made body copy feel like work
     to read. Paragraphs are --fg. --fg-faint is for micro-labels only -- 10px
     allergen codes, result counts, the inactive language -- never for a paragraph.
     Below .72 it drops under 4.5:1, so it does not go lower than this. */
  --bg:#FFFFFF;                     /* neutral, as asiahub.de is. The previous warm
                                       #FBF8F3 carried an 8-point red-over-blue cast
                                       that read as beige across a large screen. */
  --panel:#F7F7F6;                  /* a faint step DOWN from the ground, so cards
                                       and the search field still read as surfaces */
  --fg:var(--char);                 /* 10.68:1 on white */
  --fg-faint:rgba(62,62,63,.78);    /* micro-labels only */
  --fg-decor:rgba(62,62,63,.30);    /*  decoration only, contrast N/A         */

  --line:rgba(62,62,63,.16);        /* borders */
  --hair:rgba(62,62,63,.10);        /* hairline between list rows */
  --film:rgba(62,62,63,.045);       /* raised surface on --bg */
  --film-2:rgba(62,62,63,.028);     /* barely-there surface   */

  /* On the charcoal footer band, where the palette inverts. */
  --on-char:#F4EFE6;                /* 9.33:1 */
  --on-char-dim:rgba(244,239,230,.82);  /* 6.89:1 */

  --display:"Fraunces",Georgia,serif;
  --sans:"Jost","Helvetica Neue",Arial,sans-serif;
  --script:"Allura",cursive;

  /* The space above a button group. It is larger than the 16-20px between text lines
     on purpose: a button group is a change of kind, not the next line of a paragraph.
     Four different accidental values existed before this — 0px in the hero, 16px inside
     a card, 18px under the offer band, 22px elsewhere. */
  --gap-cta:clamp(24px,3.2vw,34px);
  --gap-cta-tight:clamp(18px,2vw,24px);   /* inside a card, which has its own padding */

  --shell:min(1180px,92vw);
  --ease:cubic-bezier(.2,.7,.2,1);
}


*,*::before,*::after{box-sizing:border-box}
/* both html and body: iOS Safari ignores overflow-x on body alone */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth;overflow-x:hidden}
body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:var(--sans);
  /* 400, not 300. Jost Light at 15-17px was the real reason body copy read as faint
     -- more than any colour value. Jost here is variable: 300/400/500/600 all resolve
     to the same two woff2 files and measured 389/402/423/438px wide on the same
     string, so raising it renders genuinely heavier and costs no extra bytes. */
  font-weight:400;
  font-size:clamp(15px,.4vw + 14px,17px);
  line-height:1.65;
  overflow-x:hidden;
  overflow-x:clip;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
::selection{background:var(--orange);color:#1a1204}

/* The atmosphere layer is gone. Two blurred brand-coloured radials were the last
   thing tinting the page: on near-black they read as mood, but multiplied over white
   they left a faint orange wash in the top-right corner that read as a dirty
   background rather than as warmth. The brand colours now do their work in the type,
   the buttons and the footer band, where they are deliberate. */

/* ─────────────  starburst mark (redrawn from the logo)  ───────────── */
/* height:auto + viewBox keeps the ratio in older Safari; aspect-ratio is the modern path */
.burst{display:block;fill:currentColor;height:auto;aspect-ratio:1}
.burst--hero{position:absolute;z-index:0;width:min(78vw,860px);color:var(--orange);
  top:-9%;right:-9%;opacity:.11;animation:spin 160s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ─────────────  chrome / top bar  ───────────── */
.wrap{position:relative;z-index:1}
.bar{width:var(--shell);margin:0 auto;padding:26px 0 0;
  display:flex;align-items:center;justify-content:space-between;gap:20px}
.bar__logo{display:inline-block;padding:6px 0}
.bar__logo img{width:clamp(132px,17vw,188px)}
.lang{display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:999px;
  padding:3px;background:var(--film);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.lang button{appearance:none;-webkit-appearance:none;border:0;background:transparent;
  color:var(--fg-faint);display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--sans);font-size:12px;font-weight:500;letter-spacing:.16em;
  min-height:40px;padding:0 15px;border-radius:999px;cursor:pointer;
  transition:.35s var(--ease)}
.lang button[aria-pressed="true"]{background:var(--fg);color:var(--bg)}
.lang button:hover{color:var(--fg)}
.lang button[aria-pressed="true"]:hover{color:var(--bg)}

/* ─────────────  hero  ───────────── */
.hero{position:relative;width:var(--shell);margin:0 auto;
  min-height:clamp(540px,86vh,900px);
  min-height:clamp(540px,86svh,900px);
  display:flex;flex-direction:column;
  justify-content:center;padding:clamp(34px,5.5vh,72px) 0 clamp(52px,8vh,86px);
  /* contains the bleeding starburst so the document never gets wider than the screen */
  overflow:hidden}
.hero__inner{position:relative;z-index:1}

.pill{display:inline-flex;align-items:center;gap:10px;align-self:flex-start;
  border:1px solid rgba(244,147,42,.34);border-radius:999px;
  background:rgba(244,147,42,.09);
  padding:8px 17px 8px 14px;
  font-size:11.5px;font-weight:500;letter-spacing:.2em;text-transform:uppercase;
  color:var(--green-ink);white-space:nowrap}
.dot{width:7px;height:7px;border-radius:50%;background:var(--orange);flex:none;
  box-shadow:0 0 0 0 rgba(244,147,42,.65);animation:ping 2.6s var(--ease) infinite}
@keyframes ping{
  0%{box-shadow:0 0 0 0 rgba(244,147,42,.6)}
  70%{box-shadow:0 0 0 11px rgba(244,147,42,0)}
  100%{box-shadow:0 0 0 0 rgba(244,147,42,0)}
}

.eyebrow{font-family:var(--script);font-size:clamp(34px,5.4vw,62px);line-height:.9;
  color:var(--orange-ink);margin:22px 0 -.04em;transform:rotate(-2.2deg) translateX(-.06em)}
.hero h1{font-family:var(--display);font-optical-sizing:auto;
  font-variation-settings:"SOFT" 60;
  font-weight:600;font-size:clamp(50px,10.4vw,134px);line-height:.88;letter-spacing:-.035em;
  margin:0;text-transform:uppercase}
/* vertical light-to-deep gradients echo the logo's own lettering.
   Flat brand colours are the base so the headline stays visible in any browser;
   the gradient only kicks in where background-clip:text is supported. */
.hero h1 > span{display:block;color:var(--fg)}
.hero h1 em{display:block;font-style:normal;color:var(--orange)}
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .hero h1 > span{
    background-image:linear-gradient(180deg,#FFFBF4 6%,var(--fg) 46%,#B3A48B 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent}
  .hero h1 em{
    background-image:linear-gradient(180deg,#F9CE96 4%,var(--green-ink) 34%,var(--orange) 68%,#E4801A 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent}
}

.addr{display:flex;gap:14px;align-items:flex-start;font-size:1.02rem;letter-spacing:.005em}
.addr svg{flex:none;width:17px;margin-top:5px;color:var(--green-ink)}
.addr strong{font-weight:500;color:var(--fg)}
.addr span{display:block;color:var(--fg);font-size:.95em}

/* See --gap-cta. This had no margin at all, so the hero's buttons sat flush against
   the text above them — measured 0px. */
.cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:var(--gap-cta)}
.btn{display:inline-flex;align-items:center;gap:10px;text-decoration:none;
  font-family:var(--sans);font-size:13px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  padding:15px 26px;border-radius:999px;border:1px solid transparent;
  transition:transform .4s var(--ease),background .4s var(--ease),color .4s var(--ease),border-color .4s var(--ease),box-shadow .4s var(--ease)}
/* Green, not orange. The parent site's primary button is #749D3E — sampled from its
   own rendering. Orange is the wordmark's colour and stays on the type; green is the
   brand's action colour. Dark text on the logo green measures 5.92:1; white on it is
   only 3.17:1, which is why the parent's own white-on-green button fails AA and this
   one does not copy it. */
.btn--solid{background:var(--green);color:#12190A;box-shadow:0 14px 34px -14px rgba(116,157,62,.75)}
.btn--solid:hover{background:#83AF46;transform:translateY(-2px);box-shadow:0 20px 44px -14px rgba(116,157,62,.85)}
.btn--ghost{border-color:var(--line);color:var(--fg);background:var(--film-2)}
.btn--ghost:hover{border-color:rgba(244,147,42,.55);color:var(--orange-ink);transform:translateY(-2px)}
.btn svg{width:15px;flex:none;transition:transform .4s var(--ease)}
.btn:hover svg{transform:translateX(3px)}

.scroll{position:absolute;bottom:14px;left:0;display:flex;align-items:center;gap:12px;
  font-size:10.5px;letter-spacing:.24em;text-transform:uppercase;color:var(--fg-faint);z-index:1}
.scroll i{display:block;width:52px;height:1px;background:linear-gradient(90deg,var(--fg-faint),transparent);
  animation:pull 2.4s var(--ease) infinite}
@keyframes pull{0%,100%{transform:scaleX(.4);transform-origin:left}50%{transform:scaleX(1);transform-origin:left}}

/* ─────────────  rule with mark  ───────────── */
.rule{width:var(--shell);margin:0 auto;display:flex;align-items:center;gap:22px;color:var(--green)}
.rule::before,.rule::after{content:"";height:1px;flex:1;background:var(--line)}
.rule .burst{width:26px;opacity:.85}

/* ─────────────  sections  ───────────── */
section{position:relative;z-index:1}
.shell{width:var(--shell);margin:0 auto}
.pad{padding:clamp(64px,11vh,132px) 0}
.kicker{font-size:11px;font-weight:500;letter-spacing:.28em;text-transform:uppercase;
  color:var(--orange-ink);margin:0 0 18px}
h2{font-family:var(--display);font-variation-settings:"SOFT" 60;font-weight:500;
  font-size:clamp(30px,4.4vw,54px);line-height:1.02;letter-spacing:-.02em;margin:0;text-wrap:balance}
.lede{color:var(--fg);max-width:52ch;margin:20px 0 0;font-size:1.05rem}

/* offer cards */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(255px,1fr));gap:18px;
  margin-top:clamp(38px,6vh,64px)}
.card{position:relative;padding:32px 28px 30px;border-radius:20px;
  border:1px solid var(--line);background:
    linear-gradient(180deg,var(--film),var(--film-2));
  overflow:hidden;transition:transform .5s var(--ease),border-color .5s var(--ease)}
.card::after{content:"";position:absolute;inset:auto -40% -70% -40%;height:120%;
  background:radial-gradient(circle at 50% 100%,rgba(244,147,42,.24),transparent 62%);
  opacity:0;transition:opacity .6s var(--ease)}
.card:hover{transform:translateY(-6px);border-color:rgba(244,147,42,.34)}
.card:hover::after{opacity:1}
.card > *{position:relative;z-index:1}
.card:nth-child(2){transform:translateY(14px)}
.card:nth-child(2):hover{transform:translateY(8px)}
.card:nth-child(3){transform:translateY(28px)}
.card:nth-child(3):hover{transform:translateY(22px)}
.card__num{font-family:var(--display);font-variation-settings:"SOFT" 60;font-weight:400;
  font-size:13px;letter-spacing:.2em;color:var(--orange);display:block;margin-bottom:20px}
.card h3{font-family:var(--display);font-variation-settings:"SOFT" 60;font-weight:500;
  font-size:1.5rem;line-height:1.14;margin:0 0 10px;letter-spacing:-.01em}
.card p{margin:0;color:var(--fg);font-size:.97rem}

/* location + status */
#ort{padding-top:clamp(44px,7vh,90px)}
.split{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,72px);align-items:start}
.panel{border:1px solid var(--line);border-radius:22px;background:var(--film-2);
  padding:clamp(26px,3.4vw,40px);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.panel h3{font-family:var(--display);font-variation-settings:"SOFT" 60;font-weight:500;
  font-size:1.32rem;margin:0 0 22px}
.rows{display:grid;gap:0;margin:0}
.row{display:flex;justify-content:space-between;gap:18px;padding:14px 0;
  border-top:1px solid var(--line);font-size:.96rem}
.row:first-child{border-top:0;padding-top:0}
.row dt{color:var(--fg-faint);letter-spacing:.02em}
.row dd{margin:0;text-align:right;color:var(--fg)}
.row dd small{display:block;color:var(--fg-faint);font-size:.84em;letter-spacing:.02em}
.row dd a{display:inline-block;padding:9px 0;text-decoration:none;
  border-bottom:1px solid rgba(244,147,42,.5);transition:.3s var(--ease)}
.row dd a:hover{color:var(--green-ink);border-bottom-color:var(--orange)}

.progress{margin-top:30px}
.progress__head{display:flex;justify-content:space-between;font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--fg-faint);margin-bottom:11px}
.track{height:5px;border-radius:99px;background:var(--hair);overflow:hidden}
.track i{display:block;height:100%;width:72%;border-radius:99px;
  background:linear-gradient(90deg,var(--green),var(--orange-ink) 45%,var(--orange));
  box-shadow:0 0 18px rgba(244,147,42,.5);
  animation:grow 2s var(--ease) both}
@keyframes grow{from{width:0}}

/* closing note */
.closing{border:1px solid rgba(244,147,42,.26);border-radius:24px;
  background:linear-gradient(150deg,rgba(244,147,42,.10),rgba(116,157,62,.07) 70%,transparent);
  padding:clamp(30px,4.4vw,54px);position:relative;overflow:hidden}
.closing .burst{position:absolute;right:-40px;bottom:-70px;width:270px;color:var(--orange);opacity:.10}
.closing__in{position:relative;z-index:1;max-width:50ch}

/* footer */
footer{border-top:1px solid var(--line);margin-top:clamp(40px,7vh,90px);
  padding:clamp(38px,6vh,60px) 0 40px;position:relative;z-index:1}
/* The footer's own rules all live in the "footer" section further down this file.
   What stood here was the launch page's footer — a flex row, a `.foot__brand` block
   and an `.foot h4` that no markup has emitted since the site became generated. It
   was not merely dead: `.foot{display:flex;gap:34px 48px}` still applied, so the
   three real sections were flex items carrying a 34px row gap on top of their own
   margins, and `.foot a{padding:10px 0}` stacked with `.foot li{padding:4px 0}` to
   make every link row 61px tall on a phone. Ten rows of that was most of a 1330px
   footer. Do not reintroduce a second `.foot` block here. */
.legal{margin-top:clamp(34px,5vh,54px);padding-top:22px;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:8px 26px;justify-content:space-between;
  font-size:.78rem;color:var(--fg-faint);letter-spacing:.03em}

/* reveal on scroll — uses the standalone `translate` property so it never
   fights the transform-based card stagger and hover lift. Browsers without it
   simply fade in. */
.rise{opacity:0;translate:0 26px;
  transition:opacity .9s var(--ease),translate .9s var(--ease)}
.rise.in{opacity:1;translate:0 0}

/* hero load choreography */
.anim{opacity:0;animation:up 1.05s var(--ease) both}
.anim:nth-child(1){animation-delay:.1s}
.hero .pill{animation-delay:.15s}
.hero .eyebrow{animation-delay:.28s}
.hero h1{animation-delay:.4s}
.hero .hero__meta{animation-delay:.62s}
.hero .hero__deliver{animation-delay:.74s}
.hero .scroll{animation-delay:.9s}
.bar{animation:up .9s var(--ease) both}
@keyframes up{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}

/* wide desktops get a slightly roomier measure */
@media (min-width:1700px){
  :root{--shell:min(1320px,88vw)}
  .hero h1{font-size:clamp(50px,10.4vw,152px)}
}
@media (max-width:880px){
  .split{grid-template-columns:1fr}
  .hero__inner{max-width:none}
  .card:nth-child(n){transform:none}
  .card:nth-child(n):hover{transform:translateY(-6px)}
  .scroll{display:none}
  .lang button{min-height:44px}
}
@media (max-width:520px){
  .pad{padding:clamp(52px,7vh,84px) 0}
  .btn{width:100%;justify-content:center}
  .row{flex-direction:column;gap:2px}
  .row dd{text-align:left}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important}
  .anim,.rise{opacity:1;transform:none;translate:none}
}
/* if scripting is unavailable the reveal state must never hide content */
@media (scripting:none){
  .rise,.anim{opacity:1 !important;transform:none !important;translate:none !important}
}

/* ─────────────  screen-reader-only h1  ─────────────
   Every page emits one <h1> for structure. The visually styled headline is a
   separate aria-hidden element, because the gradient-clipped display type needs
   its own markup. Defined here, not per page, so no page can render a stray
   unstyled h1. */
.vh-h1{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

/* ─────────────  skip link  ───────────── */
.skip{position:absolute;left:-9999px;top:0;z-index:99;
  background:var(--orange);color:#1a1204;padding:12px 18px;border-radius:0 0 10px 0;
  font-weight:500}
.skip:focus{left:0}

/* ─────────────  sticky site header  ───────────── */
/* Charcoal, not white. asiahub.de puts the wordmark on a #3E3E3F bar above a
   near-white body — sampled from its own rendered pixels, 724 of 817 in the bar
   region. That bar is the "black" in this brand: the logo was drawn for it. Inside
   .nav the palette therefore inverts, exactly as it does in the footer, so the
   bright accent tier applies here and the -ink tier does not (it measures ~2.2:1
   on charcoal). Opaque rather than translucent: a blurred charcoal bar over a
   white page showed the page through it as muddy grey. */
.nav{position:sticky;top:0;z-index:40;
  background:var(--char);color:var(--on-char);
  border-bottom:1px solid rgba(244,239,230,.14)}
.nav__in{width:var(--shell);margin:0 auto;min-height:64px;
  display:flex;align-items:center;gap:clamp(10px,2vw,24px)}
/* flex:0 0 auto is load-bearing: as a plain flex item the logo was shrunk to
   zero width at 320px by the phone/burger group beside it. margin-right:auto
   then pushes everything else right, which works at every width without the
   double-auto-margin gap the old sibling override was patching around. */
/* The anchor wraps only the wordmark, so its height is the image's — 28px at the
   mobile clamp. Vertical padding lifts the home link to a 44px touch target
   without changing how the logo looks; .nav__in is 64px tall, so it fits. */
.nav__logo{display:inline-flex;align-items:center;flex:0 0 auto;margin-right:auto;
  padding:8px 0}
.nav__logo img{width:clamp(104px,12vw,140px);height:auto;flex:0 0 auto}
.nav__links{display:none;gap:clamp(10px,1.6vw,22px);align-items:center}
.nav__links a{text-decoration:none;color:var(--on-char);font-size:1.02rem;font-weight:500;
  padding:8px 2px;border-bottom:1px solid transparent;transition:color .2s var(--ease)}
.nav__links a:hover,.nav__links a:focus-visible{color:var(--orange-lift)}
.nav__links a[aria-current="page"]{color:var(--on-char);border-bottom-color:var(--orange)}
.nav__end{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.nav__tel{display:inline-flex;align-items:center;gap:7px;text-decoration:none;
  color:var(--on-char);font-variant-numeric:tabular-nums;white-space:nowrap;
  min-height:44px;padding:0 6px}
/* .nav__end scoping is deliberate: a bare .nav__cta has the same specificity as
   .btn, which is declared later in this file and therefore won its display,
   showing the CTA at every width and overflowing the nav by ~370px at 320px. */
.nav__end .nav__cta{display:none}
.nav__burger{appearance:none;-webkit-appearance:none;background:transparent;
  border:1px solid rgba(244,239,230,.28);border-radius:10px;color:var(--on-char);
  width:44px;height:44px;display:grid;place-items:center;cursor:pointer;font-size:1.1rem}
/* The drawer drops out of the charcoal bar, so it stays charcoal too. */
.nav__drawer{display:none;background:var(--char);
  border-top:1px solid rgba(244,239,230,.14);padding:6px 0 14px}
.nav__drawer.open{display:block}
/* Direct children only. This was `.nav__drawer a`, which — at 0,1,1 — also beat
   `.btn` (0,1,0) on the reserve CTA nested inside .nav__drawer-cta: it forced
   display:block, so the button stopped being a flex container and its
   justify-content:center went inert, and it replaced padding:0 22px with 13px 0.
   The label therefore sat flush against the pill's left edge on every phone, with
   a stray nav-link hairline under the green. Measured at 390px: text left 16.6px
   against a button spanning 15.6–374.4px. Keep the `>`. */
.nav__drawer > a{display:block;width:var(--shell);margin:0 auto;padding:13px 0;
  text-decoration:none;color:var(--on-char);border-bottom:1px solid rgba(244,239,230,.12)}
.nav__drawer > a[aria-current="page"]{color:var(--orange-lift)}
/* The header CTA is hidden below 1100px for width, so the drawer carries it —
   otherwise a phone user would have no one-tap way to reserve once a real
   booking URL exists. */
.nav__drawer-cta{width:var(--shell);margin:16px auto 0}
.nav__drawer-cta .btn{width:100%}
@media (min-width:900px){
  .nav__links{display:flex}
  /* 900px fits the links; the CTA needs more room, so it waits for 1100px. */
  .nav__burger{display:none}
  .nav__drawer{display:none !important}
}
@media (min-width:1100px){
  .nav__end .nav__cta{display:inline-flex}
}

/* ─────────────  buttons  ───────────── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  min-height:48px;padding:0 22px;border-radius:999px;text-decoration:none;
  font-family:var(--sans);font-weight:500;font-size:.98rem;cursor:pointer;
  border:1px solid transparent;transition:transform .2s var(--ease),background .2s var(--ease)}
.btn:hover{transform:translateY(-2px)}
/* This is the rule that wins — it is declared after the launch-page block above.
   Green ground, dark text: 5.92:1. See the note on the earlier .btn--solid. */
.btn--solid{background:var(--green);color:#12190A}
.btn--solid:hover{background:#83AF46}
.btn--ghost{border-color:var(--line);color:var(--fg);background:var(--film)}
.btn--ghost:hover{border-color:var(--fg-faint)}

/* ─────────────  language switch  ───────────── */
/* The language switch lives in the header, top right — that is where people look
   for it. It used to sit after the footer, which is effectively hiding it.
   At 320px the header has only ~19px spare, so two things give way: the phone
   number collapses to its ☎ (still a tel: link, still labelled for screen
   readers — the digits are redundant when tapping dials), and only the target
   language shows. Both come back as soon as there is room. */
.nav__tel-num{display:none}
.langlink--nav{flex:0 0 auto}
.langlink--nav span[aria-current]{display:none}
@media (min-width:560px){
  .nav__tel-num{display:inline}
}
@media (min-width:900px){
  .langlink--nav span[aria-current]{display:inline-flex}
}
.langlink{display:inline-flex;border:1px solid rgba(244,239,230,.28);border-radius:999px;
  overflow:hidden;font-size:.82rem}
.langlink a,.langlink span{padding:7px 15px;text-decoration:none;min-height:44px;
  display:inline-flex;align-items:center}
.langlink span[aria-current]{background:var(--on-char);color:var(--char);font-weight:500}
.langlink a{color:rgba(244,239,230,.72)}
.langlink a:hover{color:var(--on-char)}

/* ─────────────  footer  ───────────── */
/* The footer is the page's one charcoal surface — the same plate the wordmark sat
   on before its background was made transparent, which is how the brand asset
   itself uses black. Inside this block the palette inverts, so the BRIGHT accent
   variants are the only legible ones here: --orange-ink measures 2.20:1 on
   charcoal and --green-ink 2.23:1. They are scoped to .foot, never global. */
.foot{background:var(--char);color:var(--on-char-dim);
  margin-top:clamp(48px,7vw,96px);padding:clamp(32px,5vw,60px) 0 32px}
.foot h2{color:var(--on-char-dim)}
.foot li,.foot a{color:var(--on-char-dim)}
.foot a:hover,.foot a:focus-visible{color:var(--orange-lift)}
.foot__legal{color:var(--on-char-dim)}

/* The other eight restaurants in the group. A wrapping row, not a fifth footer column:
   eight names in a column would be taller than the whole footer beside it. The old
   two-column `.locs{columns:2}` rules were from the launch page and are gone.
   Each link is a 44px touch target — they sit on their own line, so the WCAG 2.5.8
   inline exception does not apply to them. */
.foot__locs{width:var(--shell);margin:clamp(26px,4vw,40px) auto 0;padding-top:clamp(20px,3vw,26px);
  border-top:1px solid rgba(244,239,230,.14)}
.foot__locs h2{font-family:var(--sans);font-size:.78rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--on-char-dim);margin:0 0 10px}
/* .foot__locs scoping is load-bearing: `.foot ul` sets display:grid and outranks a bare
   `.locs`, which put all eight names in a single column. */
.foot__locs .locs{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:2px 22px}
.foot__locs .locs a{display:inline-flex;align-items:center;min-height:44px;padding:0 2px;
  text-decoration:none;color:var(--on-char);font-size:.94rem;
  border-bottom:1px solid transparent;transition:.25s var(--ease)}
.foot__locs .locs a:hover,.foot__locs .locs a:focus-visible{color:var(--orange-lift);border-bottom-color:var(--orange-lift)}
.foot__locs .locs__note{margin:8px 0 0;font-size:.82rem;color:var(--on-char-dim)}
.foot__legal a{color:var(--on-char-dim)}
.foot__legal a:hover{color:var(--orange-lift)}
/* Two columns on a phone, three from 620px. `auto-fit,minmax(210px,1fr)` collapsed to
   a single column below 452px and stacked every block full width — four headings and
   ten link rows in one 895px ribbon. "Karte & mehr" and "Rechtliches" are short lists
   of short words, so they sit side by side even at 320px; only the address block,
   which carries a full street line, spans both. */
.foot__in{width:var(--shell);margin:0 auto;display:grid;gap:24px 22px;
  grid-template-columns:1fr 1fr}
.foot__block--visit{grid-column:1 / -1}
@media (min-width:620px){
  .foot__in{grid-template-columns:1.5fr 1fr 1fr;gap:32px 40px}
  .foot__block--visit{grid-column:auto}
}
/* The wordmark, on the one surface it was drawn for. `alt=""` on purpose: the header
   already carries the linked, labelled logo and the legal line below spells the name
   out, so a third announcement of "asiahub Eppendorf" is noise to a screen reader.
   Not a link either — the footer's own nav lists the home page. */
.foot__logo{display:block;width:132px;height:auto;margin:0 0 18px;opacity:.92}
.foot h2{font-family:var(--sans);font-size:.78rem;letter-spacing:.14em;
  text-transform:uppercase;margin:0 0 10px}
/* One source of vertical rhythm, not three. A link is its own 44px tap target via
   min-height, so the list gap and the li need add nothing — the old stack of
   `ul{gap:9px}` + `li{padding:4px 0}` + `a{padding:10px 0}` billed 61px for a 44px
   target. Keep min-height at 44: verify fails a touch viewport under 40px. */
.foot ul{list-style:none;margin:0;padding:0;display:grid;gap:2px;font-size:.92rem}
.foot li{padding:0}
.foot__in a{display:inline-flex;align-items:center;min-height:44px;padding:0 2px;
  margin-left:-2px}
/* The two plain rows — address and hours — are read, not tapped, so they are spared
   the 44px and take a text rhythm instead. Marked with a class rather than matched
   with `li:not(:has(a))`: an unsupported :has() drops the whole rule silently, and
   this is layout, not decoration. */
/* 46ch, not 34: the hours line is ~46 characters once the split service is written
   out, and a 34ch measure forced it onto two lines even on a desktop column with
   room to spare. The address is short either way, so the wider cap costs it nothing.
   Below a laptop the grid column is narrower than this anyway and the line wraps —
   cleanly, at the space between the two day-blocks, never inside a range. */
.foot__fact{padding:5px 0;line-height:1.45;max-width:46ch}
.foot a{text-decoration:none}
.foot__legal{width:var(--shell);margin:28px auto 0;padding-top:20px;
  /* explicit colour, not the `1px solid` shorthand: without a colour the shorthand
     resets border-top-color to currentColor, which on the charcoal band is cream. */
  border-top:1px solid rgba(244,239,230,.18);display:flex;flex-wrap:wrap;gap:8px 20px;
  font-size:.85rem}

/* ─────────────  focus visibility, everywhere  ───────────── */
:focus-visible{outline:2px solid var(--orange-ink);outline-offset:3px;border-radius:4px}

/* ─────────────  utilities  ───────────── */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}
.shell{width:var(--shell);margin:0 auto}
.pad{padding:clamp(48px,7vw,104px) 0}

/* ─────────────  bottom-anchored cards: privacy notice + promo  ─────────────
   These live in site.css, not pages.css, because layout() emits them on EVERY
   page — and site.css is the only stylesheet every page loads. When they lived in
   pages.css they rendered completely unstyled on /speisekarte/ and /en/menu/,
   which load menu.css instead. Anything layout() renders belongs here. */
/* Centred, not tucked into the bottom-right corner. The offer is the marketing
   surface Google Ads will land on, and a corner card is the easiest thing on a page
   to ignore. `inset:0` + grid centring keeps it centred without transforms, so it
   cannot fight the reveal animations (which use `translate`).
   place-items:center with max-height + overflow means a long card scrolls inside
   itself on a short screen instead of overflowing the viewport. */
.promo,.notice{position:fixed;inset:0;z-index:60;
  display:grid;place-items:center;padding:16px;
  background:rgba(62,62,63,.42);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.promo__in,.notice__in{position:relative;width:100%;max-width:430px;
  max-height:calc(100vh - 32px);overflow-y:auto;
  padding:22px 24px 24px;border-radius:18px;
  border:1px solid var(--line);background:var(--panel);
  box-shadow:0 24px 70px rgba(62,62,63,.28)}
.notice__in{max-width:470px}
.promo[hidden],.notice[hidden]{display:none}
.promo__badge{margin:0 0 4px;font-size:.72rem;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--orange-ink)}
.promo__h{font-family:var(--display);font-variation-settings:"SOFT" 60;font-weight:600;
  font-size:1.16rem;line-height:1.2;margin:0 0 6px;color:var(--fg)}
.promo__body{color:var(--fg);font-size:.91rem;margin:0 0 14px}
.promo__cta{margin:0}
.promo__x,.notice__x{position:absolute;top:8px;right:8px;width:44px;height:44px;
  display:grid;place-items:center;cursor:pointer;font-size:1.4rem;line-height:1;
  background:transparent;border:0;color:var(--fg-faint);border-radius:10px}
.promo__x:hover,.notice__x:hover{color:var(--fg)}
/* The bottom-right anchoring that used to live here is gone. It survived the move to
   centred cards and quietly won above 560px, so the card was centred on a phone and
   tucked into the corner on a laptop — exactly the inconsistency it was meant to fix. */
@media (prefers-reduced-motion:no-preference){
  .promo,.notice{animation:backdropin .24s var(--ease) both}
  .promo__in,.notice__in{animation:slideup .34s var(--ease) both}
  @keyframes slideup{from{opacity:0;translate:0 14px}to{opacity:1;translate:0 0}}
  @keyframes backdropin{from{opacity:0}to{opacity:1}}
}
.notice__text{color:var(--fg);font-size:.9rem;line-height:1.55;margin:0 0 14px;
  padding-right:30px}
.notice__row{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.notice__row a{color:var(--fg);font-size:.88rem;min-height:44px;
  display:inline-flex;align-items:center}
.notice__row a:hover{color:var(--fg)}
