/* journey.css — the new user journey. (Patch P7.1.)
   ==========================================================================
   WHERE THIS COMES FROM

   Claude Design's prototype (`Reise.dc.html`) carries its visual language in
   inline styles on a 390 px phone mock. This file is that language, extracted
   once: the same palette, the same radii, the same 52 px inputs and 56 px
   primary action, the same warm paper background.

   ⛔ IT INVENTS NO VALUES. Every colour, radius and size below appears in the
   prototype. Where the prototype had to be adapted, it was for one of exactly
   three reasons, each marked ⚠️ at the rule:

     1. THE PHONE MOCK IS NOT THE PAGE. A 390 px fixed frame with a rounded
        border is the prototype's viewport; the real page IS the viewport.
     2. IBM PLEX IS NOT AVAILABLE. §7 of the briefing forbids an external font
        request and this platform self-hosts only Cairo. The Latin stack is the
        platform's own system stack — the same one lp_trial.css uses — and the
        day IBM Plex is self-hosted it is one line here.
     3. LOGICAL PROPERTIES INSTEAD OF LEFT/RIGHT, so Arabic mirrors completely
        (decision 9) without a second stylesheet.

   ⚖️ Digits are always 0–9, including in Arabic — nothing here sets
   `font-feature-settings` or a numeral system, and nothing may.

   ══════════════════════════════════════════════════════════════════════════
   🔴🔴 D3 · THE WHOLE TYPE SCALE OF THIS FILE WAS DEAD FROM P7.1 UNTIL 16.08

   Fifty-seven rules here were written as `font: 600 11.5px/1.35 inherit`. That
   declaration is INVALID CSS and every browser drops it whole: `inherit` is a
   CSS-wide keyword, legal only as the entire value of a declaration, and the
   `font` shorthand's family slot does not accept it. Measured, not deduced —
   `el.style.cssText` comes back as the EMPTY STRING after setting it.

   So for four months every one of those rules contributed nothing:
     · `.jr-lede` rendered at the browser default 16px/400, not 14.5px/400
     · `.jr-phases__name` at 16px/400, not 10.5px/700
     · `.jr-gl`, `.jr-station` (since deleted by R11), `.jr-sw`, the neighbour
       hints — all 16px/400
     · and every `<input>`, `<select>` and `<textarea>` fell back to the USER
       AGENT's 13.33px Arial, because a form control does not inherit its font
       and the one line that was supposed to give it one never applied.

   ⛔ IT LOOKED FINE, WHICH IS WHY IT SURVIVED FIFTEEN GREEN GATES. The headings
   were written as separate `font-size` / `font-weight` declarations and always
   worked; the body face reached everything else by ordinary inheritance from
   `body.jr-page`. What was missing was every SIZE and WEIGHT below a heading —
   a flat page instead of a typographic scale — and no assurance in this project
   reads a computed style, so nothing could see it. D2 self-hosted Archivo and
   the gates went green on a page that was still drawing its labels at 16px.

   ⇒ All fifty-seven are now three longhands plus an explicit `font-family:
   inherit`, which is what the shorthand was trying to say. The seven shorthands
   that name a REAL family (`var(--jr-mono)`) were always valid and are
   untouched.
   ========================================================================== */

/* --- Cairo, self-hosted ---------------------------------------------------
   The SAME two files lp_trial.css and public.css serve. Same origin, so "no
   external request" holds; and an unreferenced @font-face is never fetched, so
   the four Latin languages download nothing. */
@font-face {
  font-family: 'Cairo';
  src: url('/assets/fonts/cairo/cairo-400.ttf') format('truetype');
  font-weight: 100 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cairo';
  src: url('/assets/fonts/cairo/cairo-700.ttf') format('truetype');
  font-weight: 600 900; font-style: normal; font-display: swap;
}

/* --- Archivo, self-hosted (Welle 1 der Gestaltung, 2026-08-16) -------------
   ⭐ TWO FILES FOR EVERY WEIGHT. Claude Design's delivery names Archivo and its
   own stylesheet pulled it from Google Fonts — which §7 forbids, so it is
   hosted here. Archivo is a VARIABLE font: Google serves one file per subset
   covering the whole 100–900 axis, so the 400 of body text, the 600 of a field
   label, the 700 of a button and the 800 of a heading all come out of the same
   35 KB rather than out of four downloads.
   ⚠️ TWO SUBSETS, AND THE SECOND IS NOT OPTIONAL: Turkish (ş ğ İ ı) and Kurdish
   (ê î û ç ş) live in `latin-ext`. Shipping only `latin` would have let two of
   the five languages fall back to a system face mid-sentence.
   ⛔ The unicode-range values are Google's own, copied byte for byte — they are
   what makes the browser fetch `latin-ext` only for the languages that need it. */
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo/archivo-latin.woff2') format('woff2');
  font-weight: 100 900; font-stretch: 100%; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo/archivo-latin-ext.woff2') format('woff2');
  font-weight: 100 900; font-stretch: 100%; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ══════════════════════════════════════════════════════════════════════════
   THE PALETTE — Welle 1, taken from the delivered prototype
   ══════════════════════════════════════════════════════════════════════════
   ⭐ THE NAMES DID NOT MOVE, ONLY THE VALUES. A hundred and thirty-eight
   classes in this file already spoke through these tokens, so re-skinning the
   whole journey is a change to twenty lines rather than to every rule — and
   the screens that still carry their old markup (they are rebuilt one batch at
   a time) come along with it instead of standing out.

   Every value below appears in `reise.dc.html`. The two exceptions were marked
   ⚠️ and both were honest gaps rather than choices: the delivery does not draw a
   warning or an error state, so those two families stood in a neutral place —
   ⭐⭐ AND WELLE 2 · E2 IS THE BATCH THAT DECIDES THEM (item 4 of the delivery's
   own order: "Feld- und Transportfehler als zwei sichtbar verschiedene Dinge").
   See the two families below. */
:root {
  --jr-paper: #eef1f8;
  --jr-paper-top: #f3f5fb;
  --jr-card: #ffffff;
  --jr-quiet: #f7f9fd;
  /* F1 · R2 §B4 — the delivery's own `.note` ground (`reise.dc.html:49`). It is
     one step deeper than `--jr-quiet` and that is the point: a note has to READ
     as a tinted box on white, where the record box and the resume head are
     neutral grounds that must not. */
  --jr-note-soft: #f2f5fc;
  --jr-ink: #131936;
  --jr-muted: #454d6b;
  --jr-faint: #6e7690;
  --jr-label: #5a6180;
  --jr-line: #dfe4f0;
  --jr-line-soft: #eef1f8;
  --jr-line-strong: #c3cadd;
  --jr-field: #dfe4f0;
  /* the one loud colour of the whole journey: the primary action */
  --jr-accent: #ec3013;
  --jr-accent-hover: #dd2b0f;
  --jr-accent-ink: #ae1800;
  --jr-accent-soft: #fff1ee;
  --jr-accent-tint: #fff8f6;
  --jr-accent-line: #ffd9d1;
  --jr-disabled: #c9cede;
  --jr-green: #12b76a;
  --jr-green-soft: #e7f8ef;
  --jr-green-line: #b6ebd0;
  --jr-green-ink: #05603a;
  /* ── ⭐⭐ N18 (29.08.2026) · THE INFORMATIONAL ROLE — the journey's first blue.
     🔴 OWNER: «بدنا زر ازرق بجنب جملة نعالج بيانات طلبات زبائنك نيابةً عنك.»
     ⛔ AND IT IS A ROLE, NOT A SECOND ACCENT. §E2 above says the accent red is
     "the one loud colour of the whole journey: the primary action", and that
     stays literally true — this colour never fills the footer button, never
     appears on a submit, and marks only doors that LEAD SOMEWHERE TO READ. Two
     of them exist (the plain-language explanation and the Art.-28 agreement) and
     both are on `dpa`, the one screen that asks somebody to read before pressing.
     ⚠️ MEASURED AGAINST THE NEIGHBOURS THE WAY §E2 DEMANDS. In OKLCH
     `#1b5fd9` is hue 264.0°, against the accent's 31.4°, the green's 155° and
     the amber's 70° — no pair inside the just-noticeable difference §E2 caught
     the placeholder ramps with.
     ⚠️ AND AGAINST PAPER, NOT ONLY AGAINST HUE: `#1b5fd9` on `--jr-card` is
     5.70:1 and white on `#1b5fd9` is the same 5.70:1 — both over the 4.5:1 the
     rest of this file holds itself to for body text. */
  --jr-blue: #1b5fd9;
  --jr-blue-hover: #1750ba;
  --jr-blue-soft: #eef4fe;
  /* ══════════════════════════════════════════════════════════════════════
     E2 · THE TWO FAMILIES THE DELIVERY NEVER DREW — decided, and measured
     ══════════════════════════════════════════════════════════════════════
     ⛔ THERE WAS NOTHING TO COPY, AND THAT IS A MEASUREMENT AND NOT A COMPLAINT.
     `reise.dc.html` holds 25 distinct colours and NOT ONE of them is a red that
     is not the accent, or a yellow of any kind; the design system beside it
     (`_ds/…/styles.css`) publishes one neutral ramp and one accent ramp and has
     no danger or warning role at all. So these eight values are the server's,
     they were placeholders borrowed from another product's palette, and this is
     the batch the delivery's own §6.4 hands the decision to.

     🔴🔴 AND THE PLACEHOLDERS FAILED THE VERY SENTENCE THAT STOOD HERE. It read
     "an error is deliberately NOT the brand red … using it for refusals too
     would make 'do this' and 'this is wrong' the same signal" — and the old
     values did exactly that. Measured in OKLCH:

       --jr-accent-ink #ae1800  →  hue 31.4°
       --jr-red-ink    #912018  →  hue 29.0°     2.4° apart · ΔE 0.060

     Two point four degrees is inside the just-noticeable difference for a large
     patch, let alone for 12.5-px text. The refusal red WAS the brand red, one
     shade down, for four months.

     🔴 AND THE WARNING GROUND WAS THE "OPEN" GROUND, to four decimal places:

       --jr-accent-tint #fff8f6  ↔  --jr-amber-soft #fff7ed   ΔE 0.0114

     which is why D4 wrote that the seed question "wears the delivery's own tint,
     not the amber this file used to borrow" — the two were the same paper. An
     owner on `basisdaten` can have a tinted OPEN verify row and a warned address
     cell on screen at once, and they were painted the same colour.

     ⇒ THE RULE THIS BATCH SETTLES, and every rule below obeys it:

       RED   — a VALUE ON THIS SCREEN must change. The owner's move.
       AMBER — everything else: a moment to pass, a tab to close, our own fault.
       ACCENT— the one thing to press. Unchanged, and now alone in its hue.

     Verified before they were written down (tools/journey_view_gate.php §8b
     re-derives all of it from these very declarations, so a later retune cannot
     quietly undo it):

       hue distance   accent ↔ red-ink   23.7°     (was 2.4°)
                      accent ↔ amber-ink 54.0°
                      red    ↔ amber     77.7°
                      each   ↔ green    ≥72.3°
       contrast       every ink on every ground it is painted on ≥ 5.59 : 1
       ground ΔE      accent-tint ↔ amber-soft 0.0435   (was 0.0114)

     ⚖️ AND COLOUR IS NEVER THE ONLY SIGNAL. A refusal also carries the inset
     bar, the field border and its own sentence; a warning also carries its
     ground and its sentence. This is the platform's standing rule for a
     colour-blind reader and a printed page, and none of it is relaxed here. */
  /* AMBER — a moment must pass. Not the owner's move, and nothing is broken. */
  --jr-amber: #a07c00;
  --jr-amber-soft: #fbf3d4;
  --jr-amber-line: #eddc9c;
  --jr-amber-ink: #7a5b00;
  /* RED — a value on this screen must change. The owner's move, and the one
     family that may sit on an input. */
  --jr-red: #a30b45;
  --jr-red-soft: #fbe9ef;
  --jr-red-line: #f3c9d6;
  --jr-red-ink: #8e0f3d;
  --jr-shadow-card: 0 12px 34px rgba(24, 32, 72, .07);
  --jr-shadow-cta: 0 8px 20px rgba(236, 48, 19, .28);
  --jr-radius-card: 22px;
  --jr-radius: 14px;
  --jr-radius-sm: 12px;
  /* ⭐ Adaptation 2 IS RESOLVED: the Latin face is self-hosted now (see the
     @font-face above). The system stack stays behind it as the fallback that
     renders while a 35 KB variable font is still on the wire. */
  --jr-font: Archivo, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --jr-font-ar: Cairo, var(--jr-font);
  --jr-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --jr-heading-weight: 800;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body.jr-page {
  background: var(--jr-paper);
  /* ⭐ The ground of the delivery: a very slight vertical lift, so the white
     card reads as a card and not as the page. `background-attachment: fixed` is
     deliberately NOT used — it costs a repaint on every scroll in an in-app
     browser, which is the one environment this page must stay smooth in. */
  background-image: linear-gradient(180deg, var(--jr-paper-top), var(--jr-paper));
  background-repeat: no-repeat;
  color: var(--jr-ink);
  font-family: var(--jr-font);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  /* ⭐⭐ E3 · AND THE SHEET'S BREATHING ROOM LIVES HERE, NOT ON THE SHEET.
     It used to be a `margin-inline: clamp(…)` on `.jr-shell`, and that is
     precisely what stopped the card from centring: a fixed inline margin cannot
     be `auto` at the same time. The gutter is the PAGE's business — the ground has
     to show around the sheet or there is no sheet — and the card's business is
     only to sit in the middle of whatever room it is given.
     ⛔ THE SAME EXPRESSION, MOVED AND NOT REWRITTEN, so the two can never drift
     into two different gutters. On a phone this is arithmetically identical to
     what shipped (390 px − 2 × 9.4 px either way); from 834 px up it is the
     difference between a centred card and one glued to the front edge. */
  padding-inline: clamp(8px, 2.4vw, 24px);
}
/* ⚠️ Arabic switches the family on the ROOT, and sets no letter-spacing
   anywhere — spacing breaks the Arabic letter joins (a recorded rule).
   ⭐ 21.08.2026 · `html[lang]` IS THE CANONICAL LIVE SIGNAL. The server renders
   it and public-i18n updates it without a reload; body dir/data/class are kept
   in sync for their own contracts. One selector deliberately owns the family:
   an old secondary attribute can never strand Cairo after switching back. */
html[lang="ar"] body.jr-page {
  font-family: var(--jr-font-ar);
}
body.jr-page[dir="rtl"] * { letter-spacing: normal !important; }
/* ⭐⭐ 20.08.2026 · OWNER: "الصفحة العربية بالكامل بخط كايرو" — EVERY text on the
   Arabic screen, and the monospace token was the hole.
   Measured with CDP `CSS.getPlatformFontsForNode` on the live Arabic journey
   (which reports the face that ACTUALLY rendered, not the declaration): 1 446
   glyphs came out of Cairo and 76 out of Consolas — the language code in the
   menu and every masked value in the confirmation panel, because
   `.jr-langmenu__code` and `.jr-vrow__val` ask for `var(--jr-mono)` and that
   token knows nothing about direction.
   ⇒ THE TOKEN IS REDEFINED, NOT THE TWO RULES. A third element asking for the
   mono stack tomorrow would otherwise reopen the same hole in Arabic only, and
   this is the one line that cannot be forgotten. Nothing about the Latin four
   moves: the override lives on the RTL body.
   ⚠️ WHAT IS LEFT IS NOT TEXT: the four ✓ marks and the menu chevron fall back
   to a symbol face because Cairo carries no glyph for them — reported rather
   than "fixed" by swapping the characters for CSS shapes, which is a design
   change and the owner's call. */
html[lang="ar"] body.jr-page { --jr-mono: var(--jr-font-ar); }
/* 🔴 D3 · AND CAIRO NEEDS MORE LEADING THAN ARCHIVO AT THE SAME SIZE.
   This became visible the moment the type scale above started applying at all:
   two Arabic paragraphs in the channel question overflowed their OWN line boxes
   at 1.45 and 1.5 — measured in a real browser, `scrollHeight > clientHeight` on
   a paragraph with nothing constraining its height. Arabic ascenders and
   descenders are simply taller than Latin ones, so a leading chosen against
   Archivo clips them; it is the same family of defect as the recorded
   letter-spacing rule directly above, and it is why that rule is universal too.
   ⚖️ A FLOOR FOR RUNNING TEXT, NOT FOR HEADLINES. A 30-pixel heading at 1.7
   would drift apart; headings get their own, still looser than the Latin 1.12
   the delivery specifies. Both are RTL-only — nothing about the Latin four
   moves. */
body.jr-page[dir="rtl"] * { line-height: 1.7; }
body.jr-page[dir="rtl"] h1, body.jr-page[dir="rtl"] h2,
body.jr-page[dir="rtl"] .jr-h1, body.jr-page[dir="rtl"] .jr-h2 { line-height: 1.35; }

/* ⚠️ Adaptation 1: the phone mock becomes a column that IS the viewport on a
   phone and a centred card on a desktop, so nothing is a fixed 390 px.
   ⭐ WELLE 1 — AND THE COLUMN IS NOW THE CARD. The delivery draws a white sheet
   floating on the tinted page at every size, phone included, so the shell
   carries the card's radius and shadow from 0 px up instead of only at 560.
   The 460 px maximum is the prototype's own `main`. */
/* 🔴🔴 E3 · AND FOR FOUR BATCHES IT WAS NOT CENTRED ON ANY DESKTOP — the comment
   directly above described something this rule did not do. The rule read
   `max-width: 460px; margin: 0 auto; … margin-inline: clamp(8px, 2.4vw, 24px)`,
   and the longhand comes AFTER the shorthand: both `auto` were overwritten with
   the same fixed number, so the card sat against the front edge with all of the
   leftover room on one side. Measured in a real browser at the end of E2, on a
   screen E1 had built:

     tablet  834  de: card centre 250 against window centre 417  →  167 px off
     tablet  834  ar: 584 against 417                            →  167 px, mirrored
     desktop 1440 de: 254 against 720                            →  466 px off
     desktop 1440 ar: 1186 against 720                           →  466 px, mirrored

   ⚠️ AND IT HIT THE WIDE SCREENS TOO: at 1280+ the shell is 1120 px plus 2 × 24,
   which left 272 px of tinted page stacked entirely on one side.

   ⛔ THE SHORTHAND IS WHAT MADE IT INVISIBLE, so both axes are now stated
   explicitly and separately, and `journey_view_gate` §8c reads the LAST word on
   the inline axis rather than looking for the word `auto` anywhere — because
   `margin: 0 auto` contains `auto` and centres nothing, which was the defect. */
.jr-shell {
  display: flex; flex-direction: column;
  max-width: 460px;
  background: var(--jr-card);
  border-radius: var(--jr-radius-card);
  box-shadow: var(--jr-shadow-card);
  margin-block: clamp(10px, 2.4vw, 26px);
  /* ⇒ the gutter that used to be here is `padding-inline` on `body.jr-page` */
  margin-inline: auto;
  overflow: clip;
}
@media (min-width: 560px) {
  .jr-shell { margin-block: 24px 48px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   THREE SIZES, ONE LAYOUT — the prototype's own breakpoints
   ══════════════════════════════════════════════════════════════════════════
   `ENTSCHEIDUNGEN.md` §„Drei Größen, ein Layout": Phone 390 · Tablet 834 ·
   Desktop 1280, and the prototype's viewport switch does exactly one thing —
   it sets the stage's max-width to **460 · 820 · 1120**. Until this Nachtrag
   the shell was pinned at 460 everywhere, so a desktop visitor got a phone
   column in the middle of a 1440-pixel screen.

   ⛔ OPT-IN, ONE SCREEN AT A TIME — and that is the honest way to grow it.
   Widening the shell is only half of a desktop layout; the other half is a
   screen that USES the width ("auf dem Telefon eine Spalte, ab Tablet zwei bis
   vier"). Fourteen of the sixteen stations still carry their pre-design markup
   and would simply become a very wide single column, which is worse than a
   centred phone column. So the width is granted by `--wide`, which a page sets
   for the screens that have somewhere to put it: today the entry form and
   `basisdaten`. D4–D7 add theirs as they rebuild them.
   ⚖️ The delivery itself defers the last two desktop break-outs (week plan,
   launch list) to Welle 2 — §6.4 of its README.

   🔴🔴 G1 · 18.08.2026 — THE OPT-IN IS OVER: ALL SIXTEEN STATIONS TAKE THE
   SHEET, and the paragraph above is kept because its ⭐ half is still the law.
   The owner ("the point is not desktop only, it is EVERY screen size") had seven
   stations left at 460 px on an 834 and on a 1440 screen. The delivery was then
   measured rather than read — twenty boards × phone/tablet/desktop, in a real
   browser (`_g1_delivery.json`):

     · ITS CARD IS 366 / 772 / 1072 ON EVERY BOARD, no exception, because its
       viewport switch does exactly one thing and does it for `gesichert` as for
       `review`.
     · A SECOND COLUMN APPEARS AT 1440 ON SEVEN BOARDS ONLY, and `basisdaten`
       and `entry` are not among them. So "a screen that uses the width" was
       never the delivery's condition for GRANTING it — F3 proved that from the
       other side when the owner took the second column off `basisdaten` and kept
       its sheet ("NOTHING ELSE ABOUT THE WIDTH CHANGES").
     · AND THE LINE LENGTH IS NOT THE OBJECTION EITHER. The fear this note names
       is a sentence running the whole sheet. Measured, the delivery's own
       desktop boards paint 163 ch / 978 px (`dpa`), 150 ch (`menue_review`,
       `readiness`), 106 ch (`mb`) — and ours, board for board, are never longer
       than its (`_g1_probe_after.json`). Capping the measure here would be a
       deliberate departure from the delivery on the batch whose whole order is
       to match it, so it is recorded for the owner and not taken.

   ⇒ WHAT SURVIVES IS THE COMPOSITION HALF, and every rule below it. The width is
   granted to the sheet; whether a set spreads, a sequence reads down, or a
   receipt stays centred and capped at the delivery's own 40 ch is still asked of
   the CONTENT, one `:has()` at a time, and never of the station's name. */
@media (min-width: 834px) {
  .jr-shell--wide { max-width: 820px; }
}
@media (min-width: 1280px) {
  .jr-shell--wide { max-width: 1120px; }
}


/* --- what the width is FOR ------------------------------------------------
   🔴🔴 F3 · OWNER, 18.08.2026 — THE TWO GROUPS DO NOT STAND SIDE BY SIDE, AT ANY
   SIZE. D3 read R1 · R2 ("zwei Spalten ab 834 px … Adresse in Paaren, Kontakt in
   Paaren") together with R2 · B5's parenthesis "(Gruppe eins neben Gruppe zwei)"
   and split the master-data form into two columns of GROUPS from 834 px up. The
   owner put the delivery's own three artboards next to the built screen — Phone,
   Tablet AND Desktop — and all three draw ONE column: the address group, then
   the contact group beneath it, each the full width of the sheet.

   ⇒ "Zwei Spalten" was always about the CELLS INSIDE a group — `Anrede | Inhaber`,
   `Straße | Nr.`, `PLZ | Ort` — which is exactly what "Adresse in Paaren, Kontakt
   in Paaren" says and what `.jr-gr` has always done, at every width. The
   parenthesis was the misreading, and the delivery is the evidence: R1's own
   preamble says a drawing loses to a measurement, and here the drawing IS the
   measurement — three viewports, one column in each.

   ⚖️ NOTHING ELSE ABOUT THE WIDTH CHANGES. The sheet still grows 460 · 820 · 1120
   and the pairs inside the groups still sit side by side; what is gone is the
   split of the form itself, which also took the empty half-column of white the
   contact group left under itself on a desktop.
   ⛔ AND THE DESKTOP PANEL RULE BELOW IS A DIFFERENT QUESTION and stays: that one
   puts the CONFIRMATION PANEL beside the form on `basisdaten`, which the delivery
   does draw, and it is not this form's own columns. */
/* From desktop `basisdaten` puts the panel BESIDE the form instead of a screen
   and a half below it — the one change that turns "scroll to find out what is
   still open" into "see it while you correct it".
   ⚠️ The headline, the lede and the phase band span; the empty `#jr-verify`
   anchor is placed with the panel so the 303's fragment still lands on it. */
/* ⛔ `:has(> .jr-verify)` AND NOT THE STATION NAME — measured, not preferred.
   The ENTRY screen also renders `data-jr-screen="basisdaten"` (it IS that
   station, before there is a lead), so a rule keyed on the name alone gave the
   entry form a second column with nothing to put in it: the form was squeezed
   into 1.5fr ≈ 630 px and 450 px of the card stayed white. Seen in a desktop
   screenshot, invisible to every markup assertion.
   ⇒ The two-column layout exists exactly when there is a panel to put in
   column two, which is the honest condition and needs no list of screens. */
@media (min-width: 1280px) {
  .jr-shell--wide [data-jr-screen="basisdaten"]:has(> .jr-verify) {
    display: grid; grid-template-columns: 1.5fr 1fr;
    gap: 26px; align-items: start;
  }
  .jr-shell--wide [data-jr-screen="basisdaten"]:has(> .jr-verify) > .jr-phases,
  .jr-shell--wide [data-jr-screen="basisdaten"]:has(> .jr-verify) > .jr-h1,
  .jr-shell--wide [data-jr-screen="basisdaten"]:has(> .jr-verify) > .jr-lede { grid-column: 1 / -1; }
  /* 🔴🔴 20.08.2026 · THE `#jr-verify` RULE THAT STOOD HERE IS DELETED, AND IT IS
     WHY THIS SCREEN LOOKED BROKEN. It read `> #jr-verify { grid-column: 2;
     height: 0 }` and described an EMPTY ANCHOR DIV the page printed above the
     panel. That div is a grid item: it occupied column 2 of the form's row, so
     the panel — the next item wanting column 2 — was placed in a SECOND row.
     Measured on the live journey at 1440 px: form 217→702, panel 728→1217, one
     empty half column above the panel, another below the form, and a 1281 px
     card for 489 px of content.
     ⇒ The id now lives on the panel itself (partials/verify_panel.php), so there
     is one box and it lands in the form's own row. Anything still matching
     `#jr-verify` here would set `height: 0` on the PANEL. */
  .jr-shell--wide [data-jr-screen="basisdaten"]:has(> .jr-verify) > .jr-verify {
    grid-column: 2; margin-top: 0; padding-top: 0; border-block-start: 0;
  }
  /* The left column is now ~650 px, so the form keeps its two columns. */
}

/* --- head: the station, and its two neighbours ---------------------------- */
/* 🔴 H3 · OWNER, 19.08.2026, WITH A CORNER SCREENSHOT: "bring it down a bit so
   the padding is the same as on the right." The head's top padding was 12 and
   its side padding 14, so the language menu — now the header's only visible
   element, since the arrow moved out — sat measurably closer to the card's top
   edge than to its side. One number, stated once. */
.jr-head {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 14px 14px 10px;
}
/* ⛔ 19.08.2026 · `.jr-back` REMOVED — the in-card back arrow it styled left the
   card with owner decision H3 and lives in `.jr-nav__btn` above the sheet now.
   No markup on this platform has emitted the class since; verified by a
   recursive search of 3-monate-kostenlos and includes before deleting. */
/* ⚠️ IT IS EMPTY ON MOST SCREENS NOW AND STILL LOAD-BEARING — F1 · R11. It is
   the row's only elastic child, so it is what holds the language menu at the far
   edge; the station name it used to carry (`.jr-station`, deleted with its rule)
   is the `h1`'s alone. */
.jr-head__mid {
  grid-column: 2;
  justify-self: center;
  min-width: 0;
  text-align: center;
}
/* ⭐ 21.08.2026 · THE NEIGHBOURS ARE CENTRED ON THE SHEET, not on the room
   left after the language control. Equal flexible tracks flank the middle;
   the menu occupies the logical trailing track, so the same grid mirrors in
   Arabic without moving the middle axis by even one pixel. */
.jr-head > .jr-langmenu { grid-column: 3; justify-self: end; }
/* ⚖️ Decision 2: neighbours, not "7 of 15". Label and value are two elements,
   never one composed string — that word order is German. */
/* ⭐ WELLE 1 · THEY WRAP, THEY DO NOT SHRINK. On a 390 px phone the two hints
   plus their labels do not fit on one line, and the ellipsis that used to hide
   that turned "Speisekarte" into "Speisek…" — a station name cut in half is
   worse orientation than a second line. Measured in a real browser: eight of
   the thirteen remaining clipping notes were exactly this.

   ⭐⭐ F3 · OWNER DECISION 6 (18.08.2026): "the neighbouring station names stay
   visible, but tidily and in a form that suits where they stand." That settles
   the question F1 left open — R11's "dazwischen nichts" reads as if these two
   went with the deleted station name, `ENTSCHEIDUNGEN.md` decision 3 declares
   them part of the orientation, and the owner has now chosen decision 3.
   ⚠️ R11'S OTHER HALF IS UNTOUCHED: these name the NEIGHBOURS. The current
   station is still spoken exactly once, as the `h1`, and never in this header.

   🔴🔴 AND "TIDY" TURNED OUT TO BE A MEASUREMENT, NOT A TASTE. Measured across
   five languages × sixteen stations × three viewports: the row never wrapped —
   and the worst case, `readiness_ok` in Kurdish ("berê Pesendkirin · piştre
   Rûpela destpêkê"), painted 208 px into the 211 px the head leaves it. THREE
   pixels. One longer station name, one wider glyph, one larger default font and
   the header silently becomes two lines. So the redesign had to give width back
   rather than spend it, which rules out every treatment that adds a chip, a
   frame or an arrow.

   ⇒ THE LABEL MOVES ABOVE THE NAME. A pair costs max(label, name) instead of
   label + gap + name, which is where the room comes from; the same change is
   what makes it read as two ranks instead of four words in a row. The rule
   between the pairs is `.jr-or`'s device (R1 ratified it) and it is a LOGICAL
   border, so it mirrors itself in Arabic with no second rule.
   ⛔ AND NO LETTER-SPACING ON THE LABEL, which is the obvious way to make a
   caption look like a caption and the one this platform may not use: it breaks
   Arabic letter joins. The rank is carried by size, weight and ink instead. */
.jr-neighbours { display: flex; gap: 4px 0; justify-content: center; align-items: flex-start; flex-wrap: wrap; }
.jr-neighbour { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 0; text-align: center; }
.jr-neighbour + .jr-neighbour {
  margin-inline-start: 11px; padding-inline-start: 12px;
  border-inline-start: 1px solid var(--jr-line);
}
.jr-neighbour__label { font-family: inherit; font-weight: 400; font-size: 10px; line-height: 1.3; color: var(--jr-faint); }
.jr-neighbour__value { font-family: inherit; font-weight: 500; font-size: 11.5px; line-height: 1.3; color: var(--jr-muted); min-width: 0; overflow-wrap: anywhere; }
/* ⛔ 19.08.2026 · `.jr-lang` REMOVED — the old language PILL was replaced by the
   platform's `[data-lang-menu]` disclosure below, and nothing has emitted this
   class since. */

/* --- the platform's language menu, in the journey's palette ---------------
   ⭐ THE MARKUP IS THE PLATFORM'S (`[data-lang-menu]`, flags, endonyms, the
   check on the current one) so `public-i18n.js` drives it and remembers the
   choice for the rest of the site. Only the SKIN is the journey's, because the
   shared stylesheet that dresses this block on other pages is not loaded here —
   loading it would drag several hundred rules into a page that deliberately
   carries one.
   ⛔ AND IT WORKS WITH NO JAVASCRIPT. The list is a plain block of links; the
   toggle only becomes a real collapse once a script is there to open it, so a
   scripting-off visitor sees five languages instead of a button that does
   nothing. `[data-open]` is what public-i18n.js sets. */
.jr-langmenu { position: relative; flex: 0 0 auto; }
.jr-langmenu__toggle {
  display: inline-flex; align-items: center; gap: 7px;
  height: 38px; padding: 0 10px;
  border-radius: 11px; border: 1.5px solid var(--jr-line);
  background: #fff; color: var(--jr-ink);
  font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1;
  cursor: pointer; list-style: none; white-space: nowrap;
}
/* The default disclosure triangle would be a second chevron pointing the other
   way, and in Safari it is a marker the `list-style` above does not remove. */
.jr-langmenu__toggle::-webkit-details-marker { display: none; }
/* The ISO code, in the mono face the header already uses for the old switch. */
.jr-langmenu__code { font-family: var(--jr-mono); font-size: 12px; }
.jr-langmenu__chevron { color: var(--jr-faint); }
.jr-langmenu[open] .jr-langmenu__chevron { transform: rotate(180deg); }
/* 🔴⭐ OWNER, 19.08.2026 — ROUND, AND NOTHING CUT OFF. The five files are
   SQUARE (341 × 341, measured), so an 18 × 12 box with `object-fit: cover` was
   cropping the top and bottom off every flag — which is what "clipped" meant.
   A square box takes the whole image and `border-radius: 50%` turns it into a
   disc without removing a pixel `cover` was not already keeping.
   ⚠️ THE HAIRLINE IS NOT DECORATION: three of the five carry white at the edge
   (de, tr, ku), and on the white menu a disc without a ring loses its rim. */
.jr-langmenu__flag {
  width: 18px; height: 18px; flex: 0 0 auto;
  object-fit: cover; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(24, 32, 72, .14);
}
/* ⚖️ The open list floats over the screen instead of pushing the station title
   down — the header is sticky and a growing header would move the whole page
   under the reader's thumb. `inset-inline-end` so it hangs from the correct
   corner in Arabic without a second rule. */
.jr-langmenu__list {
  position: absolute; inset-block-start: calc(100% + 6px); inset-inline-end: 0;
  z-index: 9; display: flex; flex-direction: column; gap: 2px;
  min-width: 190px; padding: 6px;
  border-radius: var(--jr-radius); border: 1.5px solid var(--jr-line);
  background: var(--jr-card); box-shadow: var(--jr-shadow-card);
}
.jr-langmenu__item {
  display: flex; align-items: center; gap: 9px;
  min-height: 42px; padding: 0 10px;
  border-radius: 10px; background: transparent;
  color: var(--jr-ink); text-decoration: none;
  font-family: inherit; font-weight: 500; font-size: 14px; line-height: 1.3;
}
.jr-langmenu__item:hover { background: var(--jr-quiet); }
.jr-langmenu__item[aria-current="true"] { font-weight: 700; }
.jr-langmenu__item:focus-visible, .jr-langmenu__toggle:focus-visible {
  outline: 2px solid var(--jr-accent); outline-offset: 2px;
}
.jr-langmenu__label { flex: 1 1 auto; min-width: 0; }
/* ⚖️ Marked by a tick and by weight, never by colour alone. */
.jr-langmenu__check { flex: 0 0 auto; color: var(--jr-green-ink); visibility: hidden; }
.jr-langmenu__item[aria-current="true"] .jr-langmenu__check { visibility: visible; }

/* --- the banner layer: a condition sits ON the station --------------------
   ⭐⭐ E2 · A TRANSPORT REFUSAL AND A FIELD REFUSAL ARE NOW TWO SHAPES, not one
   shape in two places (item 4 of the delivery's order). The grammar is learnt
   once, at the field, and re-used here:

     · a 3-px bar on the INLINE-START edge means "a value must change" — it is
       what `.jr-gc--bad` paints on the cell, and the banner wears the same bar
       on the one transport answer that is also about a value the owner holds;
     · a dot means "a state" — nothing on this screen can be corrected, and the
       banner is telling the owner what happened rather than what to fix.

   ⛔ SO THE COLOUR IS NOT THE ONLY DIFFERENCE. `journey_view_transport_copy()`
   carries the tone, one entry at a time, decided by the one question "is this
   about a value on this screen?" — never by this stylesheet and never by a
   station name. */
.jr-banner {
  flex: 0 0 auto; margin: 0 14px 8px;
  display: flex; gap: 10px; align-items: flex-start;
  border-radius: 13px; padding: 12px 14px;
  background: var(--jr-amber-soft); border: 1px solid var(--jr-amber-line);
  color: var(--jr-amber-ink); font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5;
}
.jr-banner__dot { flex: 0 0 auto; width: 8px; height: 8px; margin-top: 6px; border-radius: 99px; background: var(--jr-amber); }
/* ⭐ `--hold` IS THE BASE SAID OUT LOUD, and the repetition is deliberate: a
   class that a page emits and this file does not answer renders at the
   browser's defaults, which is the `.jr-note` defect E1 reproduced inside a
   single batch. Every tone the vocabulary can name has a rule here. */
.jr-banner--hold { background: var(--jr-amber-soft); border-color: var(--jr-amber-line); color: var(--jr-amber-ink); }
.jr-banner--hold .jr-banner__dot { background: var(--jr-amber); }
/* The one transport answer that IS about a value: it wears the field's bar and
   the field's red, so the eye reads "same kind of thing, said at the top". */
.jr-banner--error {
  background: var(--jr-red-soft); border-color: var(--jr-red-line); color: var(--jr-red-ink);
  border-inline-start: 3px solid var(--jr-red);
}
.jr-banner--error .jr-banner__dot { display: none; }
.jr-banner--ok { background: var(--jr-green-soft); border-color: var(--jr-green); color: var(--jr-green-ink); }
.jr-banner--ok .jr-banner__dot { background: var(--jr-green); }

/* --- body ---------------------------------------------------------------- */
.jr-body { flex: 1 1 auto; padding: 4px 20px 22px; }
.jr-h1 { margin: 0 0 6px; font-size: clamp(24px, 3.2vw, 30px); line-height: 1.12; font-weight: var(--jr-heading-weight); }
.jr-lede { margin: 0 0 18px; font-family: inherit; font-weight: 400; font-size: 14.5px; line-height: 1.5; color: var(--jr-muted); }
.jr-mark { width: 44px; height: 44px; border-radius: 14px; background: var(--jr-green); margin-bottom: 20px; }

.jr-card { border-radius: var(--jr-radius); border: 1.5px solid var(--jr-line); background: var(--jr-card); padding: 14px; }
.jr-card__text { font-family: inherit; font-weight: 400; font-size: 14px; line-height: 1.55; margin: 0 0 10px; }
.jr-kv { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.jr-kv__k { font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.3; color: var(--jr-muted); }
/* ⚠️ dir="ltr" is set in the markup on the value, not here: a date is an LTR
   token inside an RTL line and the direction belongs to the element. */
.jr-kv__v { font: 500 12px/1.3 var(--jr-mono); }

/* --- fields -------------------------------------------------------------- */
.jr-fields { display: flex; flex-direction: column; gap: 14px; }
.jr-field { min-width: 0; }
.jr-label { display: flex; gap: 7px; align-items: baseline; font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.3; margin-bottom: 7px; }
.jr-label__mark { font-family: inherit; font-weight: 400; font-size: 11px; line-height: 1; color: var(--jr-faint); }
.jr-input, .jr-textarea {
  width: 100%; height: 52px;
  border-radius: var(--jr-radius-sm); border: 1.5px solid var(--jr-field); background: var(--jr-card);
  padding: 0 14px;
  /* 16px is not a style choice: anything smaller makes iOS Safari zoom on
     focus, which on this form means a horizontally scrolled page. */
  font-family: inherit; font-weight: 400; font-size: 16px; line-height: 1.4; color: var(--jr-ink);
  /* ⚖️ Free text keeps its own direction (decision 9) — an Arabic owner typing
     a Latin street name must not see it reordered. */
  unicode-bidi: plaintext;
}
.jr-textarea { height: auto; min-height: 96px; padding: 12px 14px; resize: vertical; }
.jr-input:focus-visible, .jr-textarea:focus-visible, .jr-choice:focus-visible,
/* ⛔ 19.08.2026 · `.jr-back` and `.jr-lang` dropped from this list with the rules
   they belonged to; `.jr-nav__btn` is the strip's own focusable control. */
.jr-cta:focus-visible, .jr-nav__btn:focus-visible, .jr-more:focus-visible {
  outline: 2px solid var(--jr-accent); outline-offset: 2px;
}
.jr-field--bad .jr-input, .jr-field--bad .jr-textarea { border-color: var(--jr-red); }
/* 🔴 N15-f · 29.08.2026 — AND THE ONE FIELD ON THIS JOURNEY THAT IS NOT AN INPUT.
   The logo control is a clipped `input[type=file]` plus a `.jr-drop` label
   (form_logo.php), so the rule above — the only `.jr-field--bad` declaration in
   this stylesheet — was inert on exactly the field whose refusals come from the
   server. A refused upload left `aria-invalid` and not one visible pixel: a
   screen a sighted owner could not tell from the one they had just submitted.
   ⛔ `border-color` ALONE, because the mark is a state and not a redesign — the
   dashed border, the radius and the quiet background all stay, exactly as the
   `.jr-input` arm above changes nothing but the colour. */
.jr-field--bad .jr-drop { border-color: var(--jr-red); }
.jr-error { font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.4; color: var(--jr-red-ink); margin-top: 6px; }
/* ⚖️ E1's advisory: a warning is not an error. It says "look again", and the
   owner may stand by what they typed.
   ⭐ P3.7 — this rule was written in P7.1 and NOTHING RENDERED IT until now: the
   endpoint answered 422 `confirm` and the page drew no sentence anywhere
   (deferred item 38). The border is the second half of the same statement — amber
   and not red, because nothing here is refused. */
.jr-warn { font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.4; color: var(--jr-amber-ink); margin-top: 6px; }
.jr-field--warn .jr-input, .jr-field--warn .jr-textarea { border-color: var(--jr-amber-line); }

.jr-choices { display: flex; gap: 8px; }
.jr-choice {
  flex: 1 1 0; min-width: 0; height: 48px;
  border-radius: 12px; border: 1px solid var(--jr-field); background: #fff;
  color: var(--jr-ink); font-family: inherit; font-weight: 500; font-size: 14px; line-height: 1.2; cursor: pointer;
}
.jr-choice--on { background: var(--jr-ink); color: #fff; border-color: var(--jr-ink); }
/* 🔴 F3 · OWNER, 18.08.2026 — "MEHR ANGABEN" IS A LINK, NOT A SECOND BUTTON.
   The delivery draws the disclosure as accent-coloured text at 14.5 px/600 with
   a 44-pixel touch target and nothing around it; this file gave it a full-width
   bordered white box, which on the entry screen put a control that looks like a
   primary action directly above the actual primary action. Measured against the
   delivery's own artboard: `#ec3013`, 600, no border, no ground.
   ⚖️ THE 44 PX STAYS — it is a tap target, and losing the box must not lose the
   reach. `min-height` rather than `height`, so a wrapped Kurdish or Arabic label
   grows the row instead of overflowing it.
   ⚠️ `.jr-more--sm` (the hours station's "weitere PLZ") keeps its own smaller
   size below and inherits everything else, which is what it did before. */
.jr-more {
  display: flex; align-items: center;
  min-height: 44px; margin-top: 16px; padding: 0;
  border: 0; background: none;
  color: var(--jr-accent); font-family: inherit; font-weight: 600; font-size: 14.5px; line-height: 1.3; cursor: pointer;
}
.jr-optional { display: flex; flex-direction: column; gap: 14px; margin-top: 14px; }

/* --- the foot: main action, always at the bottom -------------------------
   ⚖️ Decision 8: thumb reach, 56 px — and on a screen with no forward movement
   the foot is REMOVED by the markup rather than disabled here. A greyed-out
   primary button invites tapping.
   ⚠️ Sticky, never `position: fixed`: the deliverable says so explicitly
   because an in-app browser's chrome measures wrong against a fixed element. */
/* 🔴 OWNER, 19.08.2026 — NO RULE LINE UNDER THE LAST THING ON THE SHEET. The
   border read as a divider belonging to the content above it (on the entry that
   is "Mehr Angaben"), which it never was: it belongs to the FOOTER, and only
   while the footer is stuck over something.
   ⚖️ SO IT BECOMES DEPTH RATHER THAN A LINE. A soft upward shadow is invisible
   against white when nothing is behind it — a short screen now ends cleanly —
   and separates the bar the moment content scrolls under it, which is the one
   job the border actually had. */
.jr-foot {
  position: sticky; bottom: 0;
  flex: 0 0 auto; padding: 10px 20px 20px;
  box-shadow: 0 -10px 18px -14px rgba(24, 32, 72, .5); background: var(--jr-card);
}
/* ⚖️ 24.08.2026 · the platform consent banner now rides the journey (owner
   order — the mount at the page's foot). While it is open it overlays the
   viewport's bottom edge, exactly where this sticky footer lives; the mount's
   own height variable — the contract six public stylesheets already read —
   lifts the one action of the station above it instead of under it. */
body.cookie-banner-visible .jr-foot { bottom: var(--ui-cookie-banner-height, 0px); }
.jr-cta {
  width: 100%; min-height: 56px;
  border-radius: var(--jr-radius); border: none;
  background: var(--jr-accent); color: #fff;
  box-shadow: var(--jr-shadow-cta);
  font-family: inherit; font-weight: 700; font-size: 17px; line-height: 1.2; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  text-decoration: none;
}
.jr-cta--quiet { background: var(--jr-card); color: var(--jr-ink); border: 1.5px solid var(--jr-line); box-shadow: none; font-weight: 600; }
.jr-cta:hover { background: var(--jr-accent-hover); }
.jr-cta--quiet:hover { background: var(--jr-quiet); border-color: var(--jr-line-strong); }
.jr-cta:disabled { background: var(--jr-disabled); box-shadow: none; cursor: not-allowed; }

/* ⚖️ N10-5 · 26.08.2026 — ZWEI GLEICHWERTIGE HANDLUNGEN NEBENEINANDER.
   Die Allergen-Station trägt seit dem Eigentümerentscheid ihre beiden Knöpfe
   selbst («Weiter» · «Später prüfen»), weil BEIDE sofort weitergehen und keiner
   der Rückweg des anderen ist. ⛔ Deshalb kein `.jr-secondary` darunter: das ist
   die Klasse der TÜR (ein Weg woandershin), nicht die einer zweiten Antwort auf
   dieselbe Frage.
   ⭐ `wrap` und `flex: 1 1 …` sind der ganze Trick: auf 390 px stehen sie
   untereinander in voller Breite (Daumenziel), ab ~420 px nebeneinander. Der
   erste Knopf ist der kräftige, der zweite der ruhige — die Gewichtung sagt,
   was empfohlen ist, ohne den anderen zu verstecken. */
.jr-actions {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-block-start: 18px;
}
.jr-actions .jr-cta { flex: 1 1 15rem; }


/* --- der Rahmen ---------------------------------------------------------- */
/* FALLE: `display: none` UND NICHT `[hidden]` — `[hidden]` verliert gegen jede
   Regel, die `display` setzt, und dieses Element hat eine. Die Klasse ist der
   Zustand (dieselbe Falle, die N8 auf einer anderen Fläche bezahlt hat). */
.jr-frame { display: none; margin-block-start: 18px; }
.jr-frame.is-open { display: block; }
.jr-frame__bar {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  margin-block-end: 8px;
}
.jr-frame__close { flex: 0 1 auto; min-height: 44px; padding: 0 18px; width: auto; }
/* ⭐ `100dvh` mit `100vh` als Fallback: auf iOS ist `vh` die Höhe OHNE die
   Adressleiste, und der Rahmen würde unter ihr verschwinden. Die Reihenfolge ist
   der Fallback — ein Browser ohne `dvh` überliest die zweite Zeile. */
.jr-frame__view {
  display: block; inline-size: 100%;
  block-size: 100vh;
  block-size: 100dvh;
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card);
}
/* ⚖️ Der zweite Weg steht nur da, wo er hilft: auf einem breiten Bildschirm ist
   ein eigenes Fenster ein besserer Arbeitsplatz als ein Rahmen. Auf dem Telefon
   wäre er ein Tab-Wechsel, den diese Dosis gerade abgeschafft hat. */
.jr-win {
  display: none;
  border: 0; background: none; padding: 0;
  font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.5;
  color: var(--jr-faint); text-decoration: underline; cursor: pointer;
}
.jr-win:focus-visible { outline: 3px solid var(--jr-accent); outline-offset: 2px; }
@media (min-width: 1024px) {
  .jr-win { display: inline-block; }
}

/* --- the support path: two ways to reach a human, never a phone call ------ */
.jr-support { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.jr-support__note { margin: 0; font-family: inherit; font-weight: 400; font-size: 13.5px; line-height: 1.55; color: var(--jr-muted); }
.jr-support__link {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 16px;
  border-radius: 13px; border: 1px solid var(--jr-line); background: #fff;
  color: var(--jr-ink); font-family: inherit; font-weight: 500; font-size: 15px; line-height: 1.3; text-decoration: none;
}

/* ══════════════════════════════════════════════════════════════════════════
   P7.2 — logo, the week, the review and the final check
   ══════════════════════════════════════════════════════════════════════════
   ⚠️ EVERY RULE HERE IS DIRECTION-AGNOSTIC. No `left`, no `right`, no
   `margin-left`: the week is a grid of labels and times and Arabic reads it
   the other way, so it is flexbox and logical properties throughout. That is
   also why the "where" of an hours refusal is a row of separate chips rather
   than one sentence — the stylesheet may reorder them, a string may not. */

.jr-h2 { margin: 0 0 6px; font-family: inherit; font-weight: 700; font-size: 16px; line-height: 1.25; }
.jr-hint { margin: 0 0 10px; font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-muted); }
/* 🔴🔴 E3 · `.jr-note` HAD NINE RENDER SITES AND NOT ONE RULE, ACROSS FOUR
   BATCHES — the defect this stylesheet keeps citing and had not itself closed:
   `screen_provisioniert` twice, `screen_menue_ai` twice, `screen_allergen_entscheid`
   twice, `screen_menue_review`, `screen_menue_bestaetigung` and `list_readiness`.
   With no rule it rendered at the browser's default 16 px with 1em margins above
   and below — LARGER than the sentence it is a footnote to, and further from it
   than the block it belongs with. Every markup assertion was green, because the
   element was there and nothing was clipped; E1 reproduced the identical defect
   inside a single batch with `.jr-vrow__again` and wrote the rule down.

   ⛔ AND IT LOOKED ANSWERED TO A GREP, which is worth writing down because it is
   how it survived four batches: this file contains `.jr-note + .jr-say`, so the
   class IS in a selector — and every declaration in that rule lands on the
   `.jr-say` NEXT to it, not on the note. `journey_view_gate` §8c therefore asks
   whether a class is ever the SUBJECT of a rule, and treats a `+`/`~` as cutting
   the chain that a descendant space does not.

   ⚖️ THE SAME TYPE AS `.jr-hint`, THE OPPOSITE GAP. A hint PRECEDES the thing it
   is about and pays its margin downwards; a note FOLLOWS one and pays it upwards.
   Its bottom is zero on purpose — what comes after it is the container's business,
   and the `.jr-note + .jr-say` rule further down this file is exactly that case
   already spelled out.

   ⭐⭐ F1 · R2 §B4 — AND E3'S ONE RULE WAS THE RIGHT RULE FOR THE WRONG SET. It
   gave all nine sites the small-print treatment; Claude Design's answer splits
   them into THREE, and says why in one sentence: "neun getönte Boxen auf vier
   Screens sind Lärm, und `mu_note` viermal als Box würde die Türen zuschütten."

     · `.jr-note` — TINTED, WITH AN ICON, 13 px. Three sites, and they are the
       three sentences that must REACH the owner because they correct an
       expectation or stand before a signature: `p_long` (08) corrects "two to
       three minutes"; `ae_auto_h` (12) says what the machine filled in, directly
       above a declaration; `k_blocked_note` (14) explains a state that is
       blocking the start.
     · `.jr-fine` — SMALL PRINT, 12.5 px, grey, no ground, no icon. Five sites,
       true subordinate clauses nobody has to SEARCH for: `p_retry` (08) and
       `mu_note` (10, 11, 12, 13). This keeps E3's measured rule, under its own
       name, on the set it was actually right for.
     · and `ma_time` is not a note at all — see `.jr-wait__time`.

   ⚖️ THE ICON IS THE STYLESHEET'S, like every other mark on this journey
   (`.jr-halt__mark`, `.jr-poster__mark`, `.jr-check-row__mark`). The delivery
   draws a different line-art glyph per note; choosing three of them here would
   be inventing design, and one info mark is what all three of these sentences
   are. It is `aria-hidden` by construction — a `::before` is not in the
   accessibility tree — so the sentence beside it is read once, not twice. */
.jr-note {
  display: flex; gap: 11px; align-items: flex-start;
  margin: 12px 0 0; padding: 13px;
  border-radius: var(--jr-radius); background: var(--jr-note-soft);
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5;
  color: var(--jr-ink);
}
/* 🔴🔴 N8 (23.08.2026) · AND `hidden` HAS TO BE SAID AGAIN HERE TOO, because
   `display: flex` above already beat it. The `[hidden] { display: none }` that
   browsers ship lives in the USER AGENT stylesheet and loses to any author
   declaration whatsoever — the identical defect `.jr-said[hidden]` was written
   for, 1100 lines down, and it repeated the moment a second `.jr-note` was
   rendered hidden.
   🔬 MEASURED IN A BROWSER, WHICH IS THE ONLY PLACE IT WAS VISIBLE: on the
   building screen the markup said `hidden` and `getComputedStyle` said
   `display: flex` — so "Heute dauert es länger als sonst" stood on the screen
   from the first second of every build, under a countdown reading 3:24. Every
   gate was green: the attribute was in the markup, which is what they read. */
.jr-note[hidden] { display: none; }
.jr-note::before {
  content: "i";
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 999px;
  border: 1.5px solid var(--jr-faint); color: var(--jr-faint);
  display: grid; place-items: center;
  font-family: inherit; font-weight: 700; font-size: 12px; line-height: 1;
}
/* 🔴 F3 · AND ONE NOTE STANDS OUTSIDE `<main>`, so it needs the page's inset.
   The sentence that says the saving 422 kept the submission belongs with the
   banner it corrects, which is a direct child of the sheet — and `.jr-body`'s
   20 px padding is what keeps every other note off the card's edge. Measured
   against `.jr-banner`'s own `margin: 0 14px 8px`, so the two line up rather
   than merely both being inset.
   ⚖️ A CHILD SELECTOR, NOT A MODIFIER CLASS. There is exactly one note at this
   level and `> ` says so; a second class name would be a second thing to render,
   to translate nothing with, and to keep in the stylesheet's own census. */
.jr-shell > .jr-note { margin: 0 14px 10px; }
/* The small print. E3's rule, renamed to the treatment it actually is. */
/* 🔴 H3 · OWNER, 19.08.2026: "make this line a bit smaller and a lighter grey."
   R2 §B4 had pinned small print at 12.5 px in `--jr-muted`; the owner looked at
   the built entry screen and asked for one step quieter on both.
   ⚠️ `--jr-faint` (#6e7690) ON WHITE IS 4.51:1 — it clears AA for body text with
   nothing to spare, which is why the step stops here and not at `--jr-label`. */
.jr-fine { margin: 8px 0 0; font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.5; color: var(--jr-faint); }
/* ⭐ AND THE SECOND HOLE THE SAME AUDIT FOUND, which was in nobody's report: the
   door back into the menu module is `<form class="jr-secondary">` on four screens
   and this file declared nothing on it. It renders acceptably today only because
   a `<form>` carries no user-agent margin in Chromium — i.e. by accident of one
   browser's default, which is the fragility the audit exists to remove. It is a
   block whose whole job is to hold the quiet second action, so it says that. */
.jr-secondary { display: block; margin-block-start: 12px; }
.jr-block { margin: 0 0 22px; }
.jr-error--block { margin: -8px 0 16px; }
.jr-card--ok { border-color: var(--jr-green); background: var(--jr-green-soft); }
.jr-card--warn { border-color: var(--jr-amber-line); background: var(--jr-amber-soft); }
/* ⭐ N12 · 27.08.2026 — die leise Karte: was man wissen darf, nachdem man
   gewählt hat. Ruhigerer Grund, ruhigere Farbe, ⛔ aber KEINE kleinere Schrift
   für den Text: darin steht die Art.-13-DSGVO-Information (`mu_ai_note`), und
   eine Rechtsauskunft, die man kaum lesen kann, ist keine Auskunft. Leiser
   heißt hier: weniger Kontrast im Rahmen, nicht weniger Größe im Satz. */
.jr-card--quiet { margin-block-start: 18px; border-color: var(--jr-line); background: var(--jr-quiet); }
.jr-card--quiet .jr-card__text { color: var(--jr-muted); }
.jr-card--quiet .jr-card__text:last-child { margin-bottom: 0; }
.jr-card__title { margin: 0 0 6px; font-family: inherit; font-weight: 600; font-size: 14px; line-height: 1.35; }
.jr-file { padding: 10px 12px; height: auto; }
.jr-check { display: flex; gap: 9px; align-items: flex-start; margin-top: 10px; font-family: inherit; font-weight: 500; font-size: 13.5px; line-height: 1.4; }
.jr-check input { width: 20px; height: 20px; flex: 0 0 auto; }

/* --- the AGB / Datenschutz tick at station one (owner, 31.08.2026) --------
   ⚖️ It borrows `.jr-check` for the box itself rather than inventing a third
   look for the same control — the DPA acceptance, the allergen declaration and
   the address acknowledgement already wear it.
   ⛔ THE LINKS ARE A ROW OF THEIR OWN, BELOW the label and OUTSIDE it. Inside a
   <label> a press on "AGB lesen" can tick the box the visitor was only trying to
   read about. The indent lines them up under the sentence rather than under the
   checkbox, and it is logical (`padding-inline-start`) so Arabic mirrors it. */
.jr-terms { margin: 10px 0 0; }
.jr-terms__box { margin-top: 16px; }
.jr-terms__links { margin: 6px 0 0; padding-inline-start: 29px; display: flex; flex-wrap: wrap;
                   gap: 8px; align-items: baseline; font-family: inherit; font-size: 12.5px; line-height: 1.5; }
.jr-terms__links a { color: var(--jr-ink); text-decoration: underline; text-underline-offset: 2px; }
.jr-terms__links a:hover { color: var(--jr-accent, #4338ca); }
.jr-terms__sep { color: var(--jr-muted); }
.jr-terms__err { padding-inline-start: 29px; }
.jr-terms--done { padding-inline-start: 0; }
.jr-terms__done { display: inline-block; font-family: inherit; font-weight: 500; font-size: 13.5px;
                  line-height: 1.4; color: var(--jr-green-ink, #065f46); }

/* --- the two levels of an hours refusal ---------------------------------- */
.jr-issues { list-style: none; margin: 0 0 18px; padding: 12px 14px; display: flex; flex-direction: column; gap: 10px;
             border-radius: 14px; border: 1px solid var(--jr-red); background: #fff; }
.jr-issue { display: flex; flex-direction: column; gap: 5px; }
.jr-issue__what { font-family: inherit; font-weight: 500; font-size: 13.5px; line-height: 1.4; color: var(--jr-red-ink); }
.jr-issue__where { display: flex; flex-wrap: wrap; gap: 6px; }
.jr-chip { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 8px;
           background: var(--jr-line-soft); font-family: inherit; font-weight: 400; font-size: 11.5px; line-height: 1.5; color: var(--jr-muted); }

/* --- one day of one service ---------------------------------------------- */
.jr-day { padding: 10px 0; border-block-start: 1px solid var(--jr-line-soft); }
.jr-day:first-of-type { border-block-start: none; }
.jr-day__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.jr-day__name { font-family: inherit; font-weight: 500; font-size: 13.5px; line-height: 1.3; flex: 1 1 auto; min-width: 0; }
.jr-choices--tight { gap: 6px; flex: 0 0 auto; }
.jr-choice--sm { min-height: 34px; padding: 0 11px; font-size: 12.5px; }
.jr-window { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.jr-window__lab { font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.3; color: var(--jr-faint); }
.jr-time {
  flex: 1 1 96px; min-width: 96px; max-width: 150px; height: 44px; padding: 0 10px;
  border-radius: 11px; border: 1px solid var(--jr-field); background: #fff;
  color: var(--jr-ink); font: 400 15px/1 var(--jr-mono); -webkit-appearance: none; appearance: none;
}
.jr-more--sm { font-size: 12.5px; margin-top: 8px; }

/* --- the postcode price list --------------------------------------------- */
.jr-price { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.jr-field--sm { flex: 1 1 92px; min-width: 92px; }
.jr-field--sm .jr-label { margin-bottom: 4px; font-size: 12px; }

/* --- the review ----------------------------------------------------------- */
.jr-review { padding: 14px 0; border-block-start: 1px solid var(--jr-line); }
.jr-review:first-of-type { border-block-start: none; padding-block-start: 0; }
.jr-review__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.jr-review__head .jr-h2 { flex: 1 1 auto; margin: 0; min-width: 0; }
.jr-edit { flex: 0 0 auto; font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.3; color: var(--jr-ink); text-decoration: underline; text-underline-offset: 3px; }
.jr-review__line { margin: 0; font-family: inherit; font-weight: 400; font-size: 13.5px; line-height: 1.5; color: var(--jr-muted); }
.jr-review__plan { margin-top: 12px; }
.jr-review__sub { margin: 0 0 6px; font-family: inherit; font-weight: 500; font-size: 12.5px; line-height: 1.3; color: var(--jr-faint); }
.jr-hours { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; padding: 3px 0; }
.jr-hours__day { flex: 0 0 auto; min-width: 78px; font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.4; }
/* R-4 (N7) · the range word inside a folded day cell ("Montag bis Sonntag").
   Its own margins, because the two weekday names around it are printed with no
   whitespace between them and the element — a space in the markup would be a
   space the RTL bidi algorithm has to place, and the margin is not. */
.jr-hours__to { margin: 0 4px; font-weight: 400; color: var(--jr-faint); }
/* R-7 (N7) · the conjunction between a day's two windows. A flex ITEM of
   `.jr-hours` like the windows it separates, so it wraps with them rather than
   being stranded at the end of a line.
   🚩 AND IT WEARS `.jr-hours__lab`'s TYPE, measured on a screenshot: setting only
   weight and colour left it inheriting the row's 13px while "von"/"bis" beside it
   are 11.5px, so the joining word was the LOUDEST thing in the sentence. It is
   the same class of word as the labels it sits between and it reads as one. */
.jr-hours__and {
  flex: 0 0 auto;
  font-family: inherit;
  font-weight: 400;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--jr-faint);
}
.jr-hours__win { display: inline-flex; gap: 5px; align-items: baseline; flex-wrap: wrap; }
.jr-hours__lab { font-family: inherit; font-weight: 400; font-size: 11.5px; line-height: 1.4; color: var(--jr-faint); }
/* F1 · a day that is shut is a ROW, not a gap — and it is quieter than an open
   one, because "closed" is the absence of the times beside it and not a second
   kind of opening hour. */
.jr-hours__closed { font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.4; color: var(--jr-faint); }
.jr-hours__t { font: 500 13px/1.4 var(--jr-mono); }

/* --- the final check ------------------------------------------------------ */
.jr-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.jr-check-row { display: flex; gap: 11px; align-items: center; padding: 11px 0; border-block-start: 1px solid var(--jr-line-soft); }
.jr-check-row:first-child { border-block-start: none; }
.jr-check-row__mark { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 99px; }
.jr-check-row--ok .jr-check-row__mark { background: var(--jr-green); }
.jr-check-row--bad .jr-check-row__mark { background: var(--jr-red); }
.jr-check-row__text { font-family: inherit; font-weight: 400; font-size: 14px; line-height: 1.45; }
.jr-check-row--bad .jr-check-row__text { color: var(--jr-red-ink); font-weight: 500; }

/* --- V4 · the confirmation panel inside `basisdaten` ----------------------
   ⭐ IT INVENTS NO VALUES EITHER. The row is `jr-check-row`, the input is
   `jr-input`, the type sizes are the ones already in this file, and the two
   states use the same green and red as the final check — because "this
   criterion is met" and "this value is confirmed" are the same statement.
   ⚠️ The separator moves from the row to the ITEM: each channel is one <li>
   holding a row plus at most one sentence and one action, so a border on the
   row would draw a line between a value and its own instruction.
   ⚖️ Logical properties throughout, so Arabic mirrors with no second rule. */
.jr-verify { margin-top: 26px; padding-top: 18px; border-block-start: 1px solid var(--jr-line); }
.jr-verify__lede { margin: 0 0 6px; font-family: inherit; font-weight: 400; font-size: 13.5px; line-height: 1.55; color: var(--jr-muted); }
.jr-verify__list { gap: 0; }
.jr-vrow { padding: 4px 0 12px; }
.jr-vrow + .jr-vrow { border-block-start: 1px solid var(--jr-line-soft); }
.jr-vrow .jr-check-row { border-block-start: none; flex-wrap: wrap; }
/* The masked value: an LTR token that may sit in an RTL line, and never the
   thing that gets squeezed when the row runs out of width. */
.jr-vrow__val { flex: 1 1 auto; min-width: 0; font: 400 13px/1.45 var(--jr-mono); color: var(--jr-muted);
                overflow-wrap: anywhere; }
.jr-vrow__state { flex: 0 0 auto; margin-inline-start: auto; font-family: inherit; font-weight: 500; font-size: 12px; line-height: 1.4; }
.jr-vrow--ok .jr-vrow__state { color: var(--jr-green-ink); }
.jr-vrow--open .jr-vrow__state { color: var(--jr-red-ink); }
/* ⭐ THE ONE SENTENCE. There is never a second one under a row: a refusal takes
   this element's place rather than joining it. */
.jr-vrow__say { margin: 2px 0 0; font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5; color: var(--jr-muted); }
.jr-vrow--open .jr-vrow__say { color: var(--jr-ink); }
/* ⭐ THE ONE ACTION. On one line where there is room, wrapping on a narrow
   phone — never a fixed two-column grid that would crush the button. */
.jr-vform { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin-top: 10px; }
.jr-vform .jr-label { margin-bottom: 0; flex: 1 0 100%; }
.jr-vcode { flex: 1 1 130px; width: auto; min-width: 0;
            font: 500 16px/1.4 var(--jr-mono); letter-spacing: .18em; text-align: center; }
.jr-vbtn {
  flex: 0 1 auto; min-height: 52px; padding: 0 18px;
  border-radius: 13px; border: 1px solid var(--jr-line); background: #fff;
  color: var(--jr-ink); font-family: inherit; font-weight: 500; font-size: 14px; line-height: 1; cursor: pointer;
}
.jr-vbtn:focus-visible { outline: 2px solid oklch(0.45 0.09 250); outline-offset: 2px; }

/* --- W4 · the channel question ---------------------------------------------
   ⭐ IT INVENTS NOTHING. The heading is the panel's own `jr-verify__lede`
   rhythm, the sentence is `jr-vrow__say`, the two choices are `jr-vbtn` — the
   very button the rows above already offer — and the separator is the same
   `--jr-line-soft` that divides two rows. A block with its own visual language
   would be a second thing to learn on a screen whose whole job is reassurance.
   ⚖️ Logical properties only, so Arabic mirrors with no second rule; the chosen
   button is marked by INK AND WEIGHT, never by colour alone. */
.jr-cpref { margin-top: 14px; padding-top: 14px; border-block-start: 1px solid var(--jr-line-soft); }
.jr-cpref__t { margin: 0 0 2px; font-family: inherit; font-weight: 600; font-size: 14px; line-height: 1.45; color: var(--jr-ink); }
.jr-cpref__s { margin: 0 0 8px; font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5; color: var(--jr-muted); }
.jr-cpref__now { margin: 8px 0 0; font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.5; color: var(--jr-ink); }
.jr-cpref__note { margin: 4px 0 0; font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-muted); }
.jr-cpref__opts { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
.jr-cpref .jr-vbtn[aria-pressed="true"] {
  border-color: var(--jr-ink); font-weight: 600;
}

/* --- ⚖️ 28.08.2026 · the channel question as a real step, not a footnote ------
   Shown as an overlay ONLY while every contact row is proven and no answer is on
   file. The markup inside is the SAME `<form class="jr-cpref">` (the gate's
   substring contract holds); only a wrapping `.jr-cpmodal` decides whether it
   sits inline (answered) or on top (unanswered). No JavaScript: the form posts,
   the page reloads answered, the overlay is gone. Logical properties throughout. */
.jr-cpmodal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  padding: 16px; background: rgba(19, 25, 54, 0.55); }
.jr-cpmodal .jr-cpref { margin: 0; padding: 22px 20px 18px; width: min(100%, 440px);
  border: 0; border-radius: 16px; background: var(--jr-card);
  box-shadow: 0 24px 60px rgba(19, 25, 54, 0.28); }
.jr-cpmodal .jr-cpref__t { font-size: 18px; line-height: 1.35; margin-block-end: 6px; }
.jr-cpmodal .jr-cpref__s { font-size: 14px; margin-block-end: 14px; }
.jr-cpmodal .jr-cpref__opts { flex-direction: column; gap: 8px; padding: 0; background: transparent; }
/* ⚖️ 28.08 abends (owner): taller, and a WRAPPING flex row — icon, word, badge. At phone
   width the badge takes its own line inside the button instead of squeezing the word;
   both buttons share the height, so the pair stays a pair. */
.jr-cpmodal .jr-cpref__opts .jr-vbtn { min-height: 64px; padding: 10px 14px;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px 10px;
  border: 1.5px solid var(--jr-line-strong); background: var(--jr-card); color: var(--jr-ink);
  font-size: 15.5px; line-height: 1.3; }
.jr-cpmodal .jr-cpref__opts .jr-vbtn .jr-cpref__ico { margin-inline-end: 0; vertical-align: middle; }
.jr-cpmodal .jr-cpref__opts .jr-vbtn--reco::after { margin-inline-start: 0; white-space: nowrap; }
/* The recommended choice is marked by ground, line AND a label — never by colour alone. */
.jr-cpmodal .jr-cpref__opts .jr-vbtn--reco { border-color: var(--jr-green-ink); background: #f2fbf6; }
/* The official WhatsApp glyph beside the word (⚖️ 28.08 abends). Brand green stays as
   drawn — it is the brand's mark, not our accent. Logical margin: RTL mirrors by itself. */
.jr-cpref__ico { width: 20px; height: 20px; vertical-align: -4px; margin-inline-end: 8px; flex: none; }
/* The label is `data-reco`, drawn here — not a child node, which the i18n swap
   (textContent on every `data-i18n` element) would wipe. Logical margin: RTL-safe. */
.jr-cpref__opts .jr-vbtn--reco::after { content: attr(data-reco); display: inline-block;
  margin-inline-start: 8px; padding: 2px 8px; border-radius: 999px; vertical-align: middle;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.02em; color: var(--jr-green-ink); background: var(--jr-green-line); }
.jr-cpmodal .jr-cpref__note { margin-block-start: 12px; font-size: 12.5px; }
@media (prefers-reduced-motion: no-preference) {
  .jr-cpmodal .jr-cpref { animation: jr-cpmodal-in 180ms ease-out; }
  @keyframes jr-cpmodal-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
}

/* --- P3.6 · the last five screens ------------------------------------------
   ⭐ IT INVENTS NO VALUES. Every colour, radius and type size below is one this
   file already holds — the criteria rows reuse the final check's own row, the
   checklist reuses the verification panel's item rhythm, and the two buttons on
   a task row reuse `.jr-cta` at a smaller height. A launch screen with its own
   palette would have been a second design nobody approved.
   ⚖️ Logical properties throughout, so Arabic mirrors with no second rule. */

/* The third verdict. `blocked` is neither green nor red: nothing is wrong with
   this restaurant and nothing about it can be fixed by its owner, which is
   exactly what the amber token already means everywhere else on this page. */
.jr-check-row--blocked .jr-check-row__mark { background: var(--jr-amber-line); }
.jr-check-row--blocked .jr-check-row__text { color: var(--jr-amber-ink); }
/* The state word sits at the end of the row and never squeezes the criterion. */
.jr-check-row__text { flex: 1 1 auto; min-width: 0; }
.jr-check-row__state { flex: 0 0 auto; margin-inline-start: auto; font-family: inherit; font-weight: 500; font-size: 12px; line-height: 1.4; color: var(--jr-muted); }
.jr-check-row--ok .jr-check-row__state { color: var(--jr-green-ink); }
.jr-check-row--bad .jr-check-row__state { color: var(--jr-red-ink); }
.jr-check-row--blocked .jr-check-row__state { color: var(--jr-amber-ink); }
.jr-checks--advisory { margin-top: 4px; }

/* --- P3.7 · the one criterion that is answerable where the owner stands -----
   `notification_channel` passes on a registered device OR on the owner's own
   "I watch the panel" — and that answer lives in the launch checklist, one
   station past the gate this criterion holds shut (deferred item 129). So the
   row grows an action, and only on the criteria screen.
   ⚖️ The action wraps to its own full-width line. Putting it inside the row's
   single flex line would squeeze a criterion that is already the longest text
   on the screen in Turkish and Kurdish. */
.jr-check-row--action { flex-wrap: wrap; }
.jr-check-row__note { flex: 1 0 100%; margin: 6px 0 0; font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5; color: var(--jr-muted); }
.jr-check-row__form { flex: 1 0 100%; margin-block-start: 10px; }

/* --- the launch checklist -------------------------------------------------
   ⚠️ THE SEPARATOR IS ON THE ITEM, NOT THE ROW — the same correction the
   verification panel made: one task is a label, at most two sentences and at
   most one action, and a border on the head would draw a line between a row and
   its own instruction. */
.jr-tasks { list-style: none; margin: 0; padding: 0; }
.jr-task { padding: 12px 0; }
.jr-task + .jr-task { border-block-start: 1px solid var(--jr-line-soft); }
.jr-task__head { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
.jr-task__label { flex: 1 1 auto; min-width: 0; font-family: inherit; font-weight: 500; font-size: 14px; line-height: 1.45; overflow-wrap: anywhere; }
/* "machen wir" · "wir helfen" · "Sie selbst" — a quiet fact about the channel,
   never louder than the task it describes. */
.jr-task__cap { flex: 0 0 auto; font-family: inherit; font-weight: 400; font-size: 11.5px; line-height: 1.4; color: var(--jr-faint); }
.jr-task__state { flex: 0 0 auto; margin-inline-start: auto; font-family: inherit; font-weight: 500; font-size: 12px; line-height: 1.4; color: var(--jr-green-ink); }
.jr-task--skipped .jr-task__state { color: var(--jr-muted); }
.jr-task--done .jr-task__label, .jr-task--skipped .jr-task__label { color: var(--jr-muted); }
.jr-task__note { margin: 4px 0 0; font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5; color: var(--jr-muted); }
/* ⭐ TWO BUTTONS, WRAPPING ON A NARROW PHONE — never a fixed two-column grid
   that would crush the one row that has only a single answer. */
.jr-task__form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.jr-cta--row { flex: 0 1 auto; min-height: 44px; padding: 0 18px; width: auto; }

/* --- F1 · the row's INNER grid: text | two buttons, from 460 px -----------
   ⭐⭐ THE STACKED ROW IS A DEFECT, AND R1 SAYS WHICH HALF OF THE DESKTOP WORK
   IS WELLE 1: "Zeilen-Innengrid (Text | zwei Knöpfe): ab 460 px ja, das gehört
   zu Welle 1. Nur der Ausbruch der LISTE auf zwei Spalten ist Welle 2. Die
   gestapelte Zeile ist damit ein Defekt." Ten rows, each three lines tall,
   is a screen and a half of scrolling for ten short sentences with two buttons
   each — and the buttons are the only thing on that screen to press.

   ⛔ 460 IS ASKED OF THE LIST, NOT OF THE WINDOW. A container query, exactly
   like `.jr-grp` and `.jr-wk` above: the number that decides whether a sentence
   and two buttons fit side by side is the width of the ELEMENT they are in.
   Keying it on the viewport would give the two-column row to a 460-px phone
   whose list is 350 px wide, which is the mistake the week grid already paid
   for once.

   ⚠️ `align-items: start` AND NOT `center`. The text column can run to three
   lines (label, capability, note, and the unskippable sentence); centring the
   buttons against it would float them in the middle of a tall row and break the
   alignment of ten rows against each other. The form's own `margin-top` goes,
   because in the grid it is a column and not a following block. */
.jr-tasks { container-type: inline-size; }
@container (min-width: 460px) {
  .jr-task {
    display: grid; grid-template-columns: 1fr auto; gap: 10px 14px;
    align-items: start;
  }
  /* Everything that is not the form is the text column. */
  .jr-task > .jr-task__head, .jr-task > .jr-task__note, .jr-task > p {
    grid-column: 1;
  }
  /* 🪤 ROW 1 EXPLICITLY, NOT `1 / -1`. There are no EXPLICIT rows here — every
     row is implicit — so `-1` resolves to the end of the explicit grid, which is
     line 1, and `1 / -1` collapses to a single span that reads as a bug in one
     browser and not in the next. Placing the form at (row 1, column 2) is what
     makes the text auto-place down column 1 beside it. */
  .jr-task > .jr-task__form {
    grid-column: 2; grid-row: 1;
    margin-top: 0; flex-wrap: nowrap; align-self: start;
  }
}

/* --- the link and the code ------------------------------------------------ */
.jr-link { color: var(--jr-ink); text-decoration: underline; text-underline-offset: 3px; overflow-wrap: anywhere; }
.jr-qr { display: block; margin: 10px 0; width: 240px; max-width: 100%; height: auto; }

/* The refused acknowledgement, in the same red the field errors already use. */
.jr-check--bad { color: var(--jr-red-ink); }
.jr-field__error { margin: 6px 0 0; font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.45; color: var(--jr-red-ink); }

/* --- Conversational logo generator: one stable result rail ---------------- */
.jr-logo-ai,
.jr-logo-results { min-width: 0; }

.jr-logo-results { margin-top: 8px; }

/* 🔴🔴 N15-f · 29.08.2026 — THE `4` HERE WAS THE LAST COPY OF A NUMBER THAT
   BECAME 2 ON THE 28th. That day's pass moved CAMPAIGN_LOGO_PROPOSALS_PER_ATTEMPT
   from 4 to 2 and corrected the two readers it found — form_logo.php's
   `$logoSlotCount` and jr-logo-generator.js's `i < 4`. It read PHP and it read
   JavaScript. It did not read the stylesheet, and this rail kept declaring four
   equal tracks for two slots: on the owner's own screenshot the two grey
   skeletons sit in the left half of the AI column with the right half empty.
   ⇒ ONE NUMBER, ONE SOURCE — for the third time. The count is already in the
   markup as `data-jr-logo-slots` (the script's source since 28.08); form_logo.php
   now hands the same value to CSS as `--jr-logo-slots`, so a fourth reader cannot
   drift either. The `4` survives only as the fallback for a page drawn before
   that attribute existed.
   ⛔ AND NO RTL RULE. Grid auto-placement follows the inline direction, so the
   rail mirrors itself in Arabic; an explicit rule here would undo what the
   browser already does right (the lesson recorded at the RTL block below). */
.jr-logo-grid {
  display: grid;
  grid-template-columns: repeat(var(--jr-logo-slots, 4), minmax(0, 1fr));
  gap: 8px;
  inline-size: 100%;
  margin: 0;
}
/* ⭐ The two-slot rail's own name, which the page harness and the stations gate
   both assert by name. It carries no geometry of its own — the track count comes
   from the custom property above, so the modifier stays a NAME and never becomes
   a second place where the number lives. */
.jr-logo-grid--compact { max-inline-size: 100%; }

.jr-logo-grid[hidden] { display: none; }

/* 🔴 OW-1 · 31.08.2026 — `display: contents` WÄRE JETZT DIE FALSCHE ANTWORT UND
   ZUGLEICH EIN FEHLER. Das Formular lag früher IM Raster und musste deshalb
   durchsichtig sein, damit die Kachel darin ein Rasterfeld blieb. Es liegt jetzt
   ausserhalb, trägt nur noch versteckte Felder, und sein Knopf erreicht es über
   `form=` — genau die Bauform, die `jr-logo-redraw-form` seit N15-d benutzt.
   ⛔ UND `display: contents` HÄTTE DAS `hidden`-ATTRIBUT GESCHLAGEN (die N8-Regel:
   eine Klassenregel gewinnt gegen die UA-Regel für `[hidden]`) — das Formular
   wäre sichtbar geblieben. */
.jr-logo-pick { display: none; }

.jr-logo-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 44px;
  aspect-ratio: 1;
  inline-size: 100%;
  padding: 4px;
  overflow: hidden;
  border: 1px solid var(--jr-line);
  border-radius: 11px;
  background: #fff;
}

button.jr-logo-slot {
  color: inherit;
  font: inherit;
  cursor: zoom-in;
  touch-action: manipulation;
}

.jr-logo-pick .jr-logo-slot:hover,
.jr-logo-pick .jr-logo-slot:focus-visible {
  border-color: var(--jr-ink);
  outline: 2px solid transparent;
  box-shadow: 0 0 0 2px rgba(24, 32, 72, .12);
}

.jr-logo-slot__img {
  display: block;
  max-inline-size: 100%;
  max-block-size: 100%;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  background-color: #fff;
  background-image:
    linear-gradient(45deg, var(--jr-line-soft) 25%, transparent 25%, transparent 75%, var(--jr-line-soft) 75%),
    linear-gradient(45deg, var(--jr-line-soft) 25%, transparent 25%, transparent 75%, var(--jr-line-soft) 75%);
  background-size: 12px 12px;
  background-position: 0 0, 6px 6px;
}

.jr-logo-slot--wait {
  border-style: solid;
  border-color: #c9c9c9;
  background-color: #dedede;
  cursor: progress;
  animation: jr-logo-skeleton-pulse 1.4s ease-in-out infinite;
}

.jr-logo-slot--empty {
  border-style: dashed;
  background: var(--jr-line-soft);
  cursor: default;
}

@keyframes jr-logo-skeleton-pulse {
  0%, 100% {
    border-color: #d1d1d1;
    background-color: #e3e3e3;
  }
  50% {
    border-color: #969696;
    background-color: #a8a8a8;
  }
}

/* The preview is a progressive enhancement. Without dialog support the signed
   proposal form remains a normal submit button and selection still works. */
.jr-logo-dialog:not([open]) { display: none; }

.jr-logo-dialog {
  inline-size: min(92vw, 720px);
  max-inline-size: 720px;
  max-block-size: 92dvh;
  margin: auto;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 18px;
  background: transparent;
  color: var(--jr-ink);
}

.jr-logo-dialog::backdrop {
  background: rgba(15, 20, 40, .72);
  backdrop-filter: blur(2px);
}

.jr-logo-dialog__panel {
  position: relative;
  max-block-size: 92dvh;
  padding: 54px 18px 18px;
  overflow: auto;
  overscroll-behavior: contain;
  border: 1px solid rgba(255, 255, 255, .4);
  border-radius: 18px;
  background: var(--jr-card);
  box-shadow: 0 24px 70px rgba(15, 20, 40, .34);
}

.jr-logo-dialog__close {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--jr-ink);
  cursor: pointer;
}

.jr-logo-dialog__close:hover { background: var(--jr-line-soft); }

.jr-logo-dialog__close:focus-visible {
  outline: 2px solid var(--jr-accent);
  outline-offset: 2px;
}

.jr-logo-dialog__title {
  margin: 0 0 14px;
  padding-inline-end: 44px;
  font-family: inherit;
  font-size: 19px;
  line-height: 1.3;
  font-weight: 700;
}

.jr-logo-dialog__image-wrap {
  display: grid;
  place-items: center;
  inline-size: 100%;
  /* Keep the square from consuming the modal's whole height on wide, short
     screens; the title and 44px action row must remain inside the white panel. */
  max-inline-size: min(100%, calc(92dvh - 170px));
  margin-inline: auto;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid var(--jr-line);
  border-radius: 14px;
  background-color: #fff;
  background-image:
    linear-gradient(45deg, var(--jr-line-soft) 25%, transparent 25%, transparent 75%, var(--jr-line-soft) 75%),
    linear-gradient(45deg, var(--jr-line-soft) 25%, transparent 25%, transparent 75%, var(--jr-line-soft) 75%);
  background-size: 20px 20px;
  background-position: 0 0, 10px 10px;
}

.jr-logo-dialog__image {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
}

.jr-logo-dialog__actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
}

.jr-logo-dialog__actions .jr-cta {
  flex: 1 1 0;
  min-width: 0;
}

body.jr-logo-dialog-open { overflow: hidden; }

/* The upload remains the quiet second action. */
.jr-cta--ghost { background: #fff; color: var(--jr-ink); border: 1px solid var(--jr-field); }
/* 🔴 29.08.2026: `.jr-logo-send` war der leise Weiter-Knopf am Upload-Block.
   Der Inhaber hat die Gewichtung umgedreht — der Weg vorwaerts ist jetzt die
   rote Fusszeile — und der Knopf ist fort. Seine Regel geht mit: eine Regel
   ohne Auslieferung wird beim naechsten Umbau als Wahrheit gelesen. */
.jr-card--bad { background: #fff; border-color: var(--jr-red); color: var(--jr-red-ink); }

@media (max-width: 420px) {
  .jr-logo-grid { gap: 6px; }
  .jr-logo-dialog {
    inline-size: calc(100vw - 20px);
    max-block-size: calc(100dvh - 20px);
  }
  .jr-logo-dialog__panel {
    max-block-size: calc(100dvh - 20px);
    padding: 52px 12px 12px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .jr-logo-slot--wait {
    border-color: #b8b8b8;
    background-color: #d7d7d7;
    animation: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   Welle 1 — the phase bar and the success stripe
   ══════════════════════════════════════════════════════════════════════════ */

/* --- orientation: a word and five segments, never a fraction --------------
   ⚠️ The segments are `flex` and use no left/right anywhere, so Arabic mirrors
   the direction of travel with the rest of the page and the first segment sits
   where the reading starts. */
/* 🔴🔴 H2 · OWNER, 19.08.2026 — THE BAND IS A WORD NOW, ON EVERY SCREEN, and
   five rules left this file with the two things it stopped drawing: the accent
   tile (`__icon`, `__lead`) and the pips (`__bar`, `__seg`, `__seg--done`,
   `__seg--now`).
   ⭐ AND `--word` WENT WITH THEM RATHER THAN SPREADING. It existed to mark the
   ONE screen that drew the word alone (`provisioniert`, whose clock takes the
   end of the row — R4: "die Uhr besetzt das Zeilenende — das war keine
   Auslassung"); with every screen drawing the word alone there is no second
   composition for a modifier to name, so its two declarations become the base.
   `space-between` had nothing left to space, and the 14 px under a row that now
   holds one small label closes to the 6 px the delivery draws above a headline. */
.jr-phases {
  display: flex; align-items: center; justify-content: flex-start; gap: 12px;
  margin: 0 0 6px;
}
.jr-phases__name {
  font-family: inherit; font-weight: 700; font-size: 10.5px; line-height: 1.3; letter-spacing: .1em; text-transform: uppercase;
  color: var(--jr-label); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ⚠️ Arabic gets no letter-spacing (the rule above clears it with !important);
   uppercasing does nothing to an Arabic string either, so the same class is
   simply a bold small label there. Both are correct without a second rule. */

/* --- the success stripe --------------------------------------------------
   Green, because it is the only thing on the journey that means "done" — and
   the same green the readiness list uses for a criterion that is met. */
/* 🔴 F1 · R5 — THE MARGIN THAT PAID FOR STANDING OUTSIDE `<main>` IS GONE. The
   stripe used to be emitted between `</header>` and `<main>`, where nothing
   supplied an inline inset, so it carried its own 14 px — four pixels narrower
   on each side than the screen it belonged to, on every station that showed it.
   It now sits inside `main.jr-body`, under the band, and inherits that element's
   own 20-px inline padding like the `h1` beneath it. */
/* ── 🔴 N18 (29.08.2026) · OWNER — IT SAT TOO CLOSE TO THE LANGUAGE MENU ──────
   «اول شيء نزل حاوية اجتاز الفحص لتحت شوي صغيرة مشان تبعد عن حاوية اللغات.»
   Measured cause: R5 moved the stripe INSIDE `main.jr-body`, and that element's
   own `padding-block-start` is 4 px (0 on mobile) — so the stripe's top edge
   stood 4 px under the header that carries `.jr-langmenu`, reading as one block
   with it. The gap is the stripe's own margin rather than the body's padding,
   because the padding is shared with the `h1` of every screen that shows no
   stripe at all and widening it would move all seventeen.
   ⚖️ AND IT SHRANK IN THE SAME BREATH — the second half of one sentence. It is
   a receipt for something already finished, standing above the `h1` that names
   what to do NEXT; at 14.5 px bold it out-weighed that heading. */
.jr-ok {
  flex: 0 0 auto; margin: 10px 0 12px;
  display: flex; align-items: center; gap: 9px;
  padding: 7px 11px; border-radius: var(--jr-radius);
  background: var(--jr-green-soft); border: 1.5px solid var(--jr-green-line);
}
.jr-ok__dot {
  width: 18px; height: 18px; flex: 0 0 auto; border-radius: 99px;
  background: var(--jr-green); color: #fff;
  display: grid; place-items: center; font-family: inherit; font-weight: 700; font-size: 10px; line-height: 1;
}
.jr-ok__text { flex: 1 1 auto; min-width: 0; font-family: inherit; font-weight: 700; font-size: 13px; line-height: 1.35; color: var(--jr-green-ink); }
.jr-ok__label {
  flex: 0 0 auto; font-family: inherit; font-weight: 700; font-size: 10px; line-height: 1; letter-spacing: .08em;
  text-transform: uppercase; color: var(--jr-green-ink);
}

/* ══════════════════════════════════════════════════════════════════════════
   D3 — the grouped field block, the twin switch, the segmented answer
   ══════════════════════════════════════════════════════════════════════════
   ⭐⭐ THE PREFIX IS THE POINT. The delivery names these primitives `.grp` `.gr`
   `.gc` `.gl` `.gi` — five one- and two-letter class names in the global scope
   of pages that also load the platform's own stylesheets. `jr-` in front of each
   is the entire difference between a field row and a collision, and it costs
   nothing: the markup is ours.

   ⛔ IT INVENTS NO VALUES. Every colour, radius, weight and pixel below stands in
   `reise.dc.html`'s own <style> block. Where a value was adapted it is marked ⚠️
   at the rule and the reason is one of exactly two:
     1. FIVE LANGUAGES, NOT ONE. The prototype is written in German; Turkish and
        Kurdish labels are longer and must wrap rather than clip.
     2. A KEYBOARD IS NOT A FINGER. The prototype's focus ring sits on the group;
        a row of three cells needs to say WHICH cell has the caret.
   ⚖️ Logical properties throughout, so Arabic mirrors with no second rule — the
   delivery's own `.gc + .gc { border-inline-start }` already reads that way. */

/* --- the group: one bordered card, many borderless cells ------------------ */
.jr-grp {
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card); overflow: hidden;
}
/* The GROUP lights up, not the cell: the cells carry no border of their own, so
   a ring around one of them would be a ring around nothing. */
/* 🔴 OWNER, 19.08.2026 — THE GROUP NO LONGER LIGHTS UP. Tapping one cell drew a
   red rectangle around ALL of them (five rows on the address group), which reads
   as "this whole block is wrong" on a screen where red is the error colour.
   ⛔ AND THE FOCUS IS NOT LOST WITH IT — that would be the real defect. The ring
   that matters is on the CELL, one rule below (`.jr-gi:focus-visible`), and it
   is a keyboard-only indicator, which is where a focus ring belongs. */
.jr-grp + .jr-grp { margin-top: 12px; }
.jr-gr { display: flex; align-items: stretch; border-block-start: 1.5px solid var(--jr-line-soft); }
.jr-grp > .jr-gr:first-child { border-block-start: 0; }
/* ⚠️ THE VERTICAL PADDING IS ON THE LABEL AND THE CONTROL, NOT ON THE CELL, and
   that is an accessibility fix rather than a preference. The delivery writes
   `padding: 7px 14px` here, which leaves a 7-pixel strip at the top and bottom
   of every cell that LOOKS like part of the field and does nothing when a thumb
   lands on it. Moving the same seven pixels inside the two children makes the
   label and the control tile the cell exactly — every pixel of a 55-px cell now
   either focuses the field (the label carries `for=`) or is the field. The
   rendering is identical to the prototype's; only the dead strip is gone. */
.jr-gc {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; justify-content: center;
  padding: 0 14px;
}
.jr-gc + .jr-gc { border-inline-start: 1.5px solid var(--jr-line-soft); }
/* The three widths the delivery pins by hand, as classes rather than inline
   styles: a house number, a postcode and a country are the only cells in the
   whole form that must not be an equal third of their row. */
/* ⭐⭐ F2 · BACK TO THE DELIVERY'S 86, BECAUSE THE REASON FOR 96 IS GONE.
   D3 widened this cell by ten pixels for a measured reason: the English
   required-mark renders at 59 px, an 86-px cell leaves 57 px of content, and
   "required" overflowed its own label by two pixels in all three viewports
   (invisible in German — "Pflicht", 39 px). That was a true measurement about a
   cell that PRINTED a mark.
   ⇒ R12 stopped printing it. The mark is drawn only where a cell's norm differs
   from its block's, and `hausnummer` is a required cell in the required block —
   so the widest thing in it is now the label alone, and the number the delivery
   pinned fits it. Re-measured in five languages × three viewports by
   `_f1_probe.js`: the label stays on one line and nothing is cut.
   ⛔ AND THE PLZ CELL DOES NOT MOVE WITH IT. R1 answered that one separately —
   "PLZ-Zelle: EINE Primitive für beide (96 px)" — so the two numbers are two
   decisions, and the day a mark returns to a pinned cell, that cell widens then. */
.jr-gc--nr { flex: 0 0 86px; }
.jr-gc--plz { flex: 0 0 96px; }
/* --- H2 · the country, a choice again -------------------------------------
   🔴🔴 OWNER, 19.08.2026 — the fixed line is gone and `.jr-gc--land` is back at
   the delivery's own 34 %. F1's block here explained why a list of one was a
   fact rather than a field; the owner has decided it is a field, so the cell is
   sized like the two it shares the row with and the chevron below is drawn for
   it like for any other `<select>`.
   ⛔ `.jr-gc--fixed` AND `.jr-gv` ARE DELETED, NOT LEFT LYING. `land` was their
   only caller — a rule kept "in case" is the second place a future reader has to
   decide which of two shapes is current. */
.jr-gc--land { flex: 0 0 34%; }
/* ⚠️ 46 % rather than the prototype's 44: "Ohne Anrede" is the widest of the
   three German options and the longest of the five languages' equivalents, and
   at 44 % of a narrow group it lost its last letter. */
.jr-gc--sal { flex: 0 0 46%; }
/* ⚠️ THE ROW STILL WRAPS ON A NARROW GROUP, and the question is about the
   GROUP's width and not the window's — a container query and not a media query.
   Measured twice while the country was still a `<select>`: the first fix keyed
   on the viewport and was right on a phone and WRONG on a desktop, where the
   same group sits in a 630-px column and clipped again ("Deutschl…", caught in a
   screenshot). The group asks about itself, so it is right at every size and in
   all five languages.
   🔴 F1 · THE CELL THAT MOTIVATED THIS IS GONE. The country is a fixed line on
   its own row now, so the `.jr-gc--land` arm that used to break it out at 400 px
   has nothing to select — but `flex-wrap` stays, because it is what lets ANY
   three-cell row (`plz | ort`, `strasse | hausnummer`) fold instead of crushing
   its narrowest cell. The rule is kept for the property it provides, not for the
   cell it was written for.
   ⛔ Shrinking the type instead would have crossed the 16-px floor that stops
   iOS zooming the page on focus, which on this form means a horizontally
   scrolled page — the exact defect the row exists to avoid. */
.jr-grp { container-type: inline-size; }
@container (max-width: 400px) {
  .jr-gr { flex-wrap: wrap; }
}
/* ⛔ AND A FLOOR UNDER BOTH OF THEM. A <select> does not report its truncation
   the way a paragraph does — `scrollWidth` stays equal to `clientWidth`, so the
   browser gate's clipping test cannot see it and the first two versions of this
   rule shipped a silently cut country name. An ellipsis is not a fix, it is the
   evidence that one is needed; it is here so the failure degrades legibly, and
   the gate now measures select truncation directly. */
select.jr-gi { text-overflow: ellipsis; }
/* 🔴🔴 H2 · AND THE ADDRESS ROW WRAPS BEFORE IT CUTS. `plz | ort | land` is the
   delivery's row and the owner asked for it back; on a 390-px phone the 34 % the
   country gets is 112 px, and "Deutschland" does not fit in it — measured, in
   German and in English, the moment the `<select>` returned.
   ⛔ A CONTAINER QUERY, NEVER A MEDIA QUERY, and F1 recorded why: the same group
   sits in a 630-px column on a desktop `basisdaten`, so a rule keyed on the
   WINDOW was right on a phone and wrong there. The question is how wide the
   GROUP is, which is the only thing the cells inside it can answer to.
   ⚠️ THE ROW GIVES WAY IN ONE PLACE ONLY — the country takes a line of its own
   and `plz | ort` keep theirs, which is the arrangement F1 shipped for a year
   and the one the owner is used to on a phone. Above the threshold all three
   share the row, exactly as the delivery draws it. */
@container (max-width: 460px) {
  .jr-gr:has(> .jr-gc--land) { flex-wrap: wrap; }
  .jr-gr > .jr-gc--land {
    flex: 1 1 100%;
    border-inline-start: 0;
    border-block-start: 1.5px solid var(--jr-line-soft);
  }
}
/* ⚠️ AND IT WRAPS RATHER THAN CLIPS. "PLZ · Pflicht" is two words in a 96-pixel
   cell; in Turkish and Kurdish the second one is longer than the first. A
   station name cut in half was already the lesson of D2's neighbour hints. */
.jr-gl {
  display: flex; gap: 5px; flex-wrap: wrap; align-items: baseline;
  padding-block-start: 8px;
  font-family: inherit; font-weight: 600; font-size: 11.5px; line-height: 1.35; color: var(--jr-label);
}
/* ⛔ AND A FLOOR UNDER ALL FIVE LANGUAGES. Widening the cell fixes the word this
   batch measured; this stops the NEXT one. A flex item will not shrink below its
   longest word, so without these two declarations a single long label in a
   language nobody sized for overflows its cell instead of breaking — which is
   what "required" did. Nothing breaks while it fits, so no language that fits
   today looks any different. */
.jr-gl > span { min-width: 0; overflow-wrap: anywhere; }
/* "freiwillig" — the exception, and the only mark the screen prints. Quieter
   than the label it follows, because it qualifies that label rather than
   competing with it. */
.jr-gl__mark { font-size: 10.5px; font-weight: 400; color: var(--jr-faint); }
.jr-gi {
  width: 100%; box-sizing: border-box;
  min-height: 34px; padding: 0 0 8px;
  font-family: inherit; font-weight: 500; font-size: 16px; line-height: 1.4; color: var(--jr-ink);
  background: transparent; border: 0; border-radius: 4px;
}
.jr-gi::placeholder { color: var(--jr-faint); font-weight: 400; }
/* ⚠️ ADAPTATION 2. The delivery clears the outline here and lets the group's
   glow carry focus. That works for one cell per row; PLZ · Ort · Land is three,
   and a keyboard user tabbing through them would see the same glow three times
   without ever learning where the caret is. The group still glows — this only
   adds which cell inside it is live, and only for a keyboard (`:focus-visible`),
   so a finger sees exactly the delivery's design. */
.jr-gi:focus { outline: none; }
/* 🔴🔴 OWNER, 19.08.2026, TWICE — "I do NOT want the red rectangle to appear
   when the user wants to type." The 2-px accent outline drew a hard red box
   around the cell on click, and on a screen where red is the ERROR colour a box
   that appears the moment somebody starts typing reads as a refusal.
   ⛔ BUT FOCUS MAY NOT SIMPLY VANISH — a control with no visible focus state is
   a keyboard user with no cursor. So the rectangle becomes a LINE: 2 px along
   the bottom edge of the live cell, which is the shape a text field has carried
   since paper forms and cannot be mistaken for a frame around an error.
   ⚠️ `box-shadow: inset` RATHER THAN A BORDER, because these cells are flex
   items whose widths the row depends on (`jr-gc--plz` is 96 px exactly); a real
   border would take two of those pixels from the field. Same idiom, same reason,
   as `.jr-gc--bad` further down — and like it, the inset X offset is 0 here, so
   there is nothing to mirror in Arabic. */
.jr-gi:focus-visible { outline: none; }
.jr-gc:has(> .jr-gi:focus-visible) { box-shadow: inset 0 -2px 0 var(--jr-accent); }
/* ⛔ AND A FALLBACK THAT IS NOT "NOTHING". A browser without `:has()` never
   matches the rule above, so it would show no focus at all — worse than the box
   the owner asked to remove. There, the field keeps a plain underline of its
   own; where `:has()` works the cell-level rule paints over it. */
@supports not selector(:has(*)) {
  .jr-gi:focus-visible { outline: none; border-block-end: 2px solid var(--jr-accent); }
}
/* A <select> is an input in this grammar: same type, same box, and its own
   chevron because the browser's would arrive with the browser's border.
   ⚠️ FORM CONTROLS DO NOT INHERIT font-family IN ANY ENGINE — they start from
   the UA stylesheet. `.jr-gi` says `font: … inherit`, which is what stops the
   Arabic country list from rendering in Times while its label is Cairo. The
   same sentence is written over `lp_trial.css`'s control rules; this is the
   journey's first <select>, so it is the first time it applies here.
   ⚖️ And the chevron is mirrored by hand: a `background-position: right` with
   no RTL twin parks the arrow on top of the Arabic word. */
select.jr-gi {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  padding-inline-end: 18px;
  background-repeat: no-repeat;
  background-size: 11px;
  background-position: right 0 top 12px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7' fill='none'%3E%3Cpath d='M1 1l4.5 4.5L10 1' stroke='%236e7690' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}
[dir="rtl"] select.jr-gi { background-position: left 0 top 12px; }
/* The one cell that keeps a textarea — see the partial for why. */
textarea.jr-gi { min-height: 46px; resize: vertical; }
/* ⚖️ Free text keeps its own direction (decision 9): an Arabic owner typing a
   Latin street name must not see it reordered. */
.jr-gi--free { unicode-bidi: plaintext; }
/* ⚖️ And a number is an LTR token in any language, with digits that line up.
   ⛔ Digits stay 0–9 in Arabic — nothing here sets a numeral system. */
.jr-gi--num { direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums; }
/* The refusal and the pause, in the vocabulary the flat fields already use.
   🔴🔴 E2 · AND THE BAR WAS ON THE WRONG EDGE IN ARABIC SINCE D3. `box-shadow:
   inset` takes an X OFFSET and there is no logical form of it, so `inset 3px`
   paints the LEFT edge of the cell in every writing direction — which is the
   cell's LEADING edge in four languages and its TRAILING edge in the fifth. That
   is precisely the defect E1 measured on `.jr-resume` (`border-left` against
   `border-inline-start`, three of fifteen views), one class along, and it has
   been live on every Arabic address refusal since D3. Nothing could see it: the
   element is present, nothing is clipped, and the four LTR languages render
   byte-identically.
   ⛔ FLIPPED RATHER THAN CONVERTED TO A BORDER: a real `border-inline-start`
   would add three pixels to a cell whose width is a flex basis the row depends
   on. Same idiom, same reason, as the `<select>` chevron four rules above. */
.jr-gc--bad { background: #fff; box-shadow: inset 3px 0 0 var(--jr-red); }
[dir="rtl"] .jr-gc--bad { box-shadow: inset -3px 0 0 var(--jr-red); }
.jr-gc--warn { background: var(--jr-amber-soft); }
.jr-gc .jr-error, .jr-gc .jr-warn { margin-top: 3px; }

/* --- the twin switch: a shortcut, never a condition ----------------------- */
/* ⚠️ ADAPTATION 1. The delivery sets `padding: 0 14px` against a 46 px minimum,
   which is exact for one German line. "WhatsApp aynı numara üzerinden çalışıyor"
   wraps to two on a 390 px phone, and zero vertical padding would have clipped
   the second line against the row below. */
/* --- H2 · the twin a tick makes unnecessary --------------------------------
   🔴🔴 OWNER, 19.08.2026 — "when the WhatsApp number is the same as the phone,
   hide the WhatsApp field, and bring it back when the tick is cleared; the same
   for the second e-mail."

   ⚖️ IT REVERSES R1, AND R1 WAS RIGHT ABOUT THE MECHANISM, WHICH IS WHY THIS IS
   CSS AND NOT A SCRIPT. Claude Design withdrew his own `data-wa-row` hiding —
   "Euer Verhalten (beide Zwillinge immer sichtbar, Häkchen serverseitig geehrt)
   ist richtig und besser als das Ausblenden, das ich gezeichnet hatte" — and the
   reason it was better is that a journey which must work without JavaScript
   cannot hide a field with JavaScript. `:has()` is not JavaScript: the tick is a
   real `:checked` state, the browser re-evaluates it on every click, and a
   browser too old to know the selector simply shows both fields, which is
   exactly the behaviour R1 ratified. There is no state to lose, nothing to
   rehydrate, and the no-script journey is untouched.

   ⛔ HIDDEN, NEVER DISABLED — and that is the whole safety of it. A
   `display: none` control is still submitted, so a value the owner may have
   typed still reaches the endpoint and `campaign_lead_twin_fields()` still
   decides what it means. Disabling would drop the field from the POST and turn a
   visual shortcut into a data change.
   ⚠️ THE SELECTOR IS AN ADJACENCY THE MARKUP ALREADY HAD: the tick's label sits
   directly above the row it fills ("THE TICK SITS ABOVE THE FIELD IT FILLS,
   never in place of it"), so nothing was added to the markup to hook it. */
/* 🔴🔴 19.08.2026 · A ROW THAT CARRIES A REFUSAL IS NEVER HIDDEN. (Audit B3.)
   The row holds the input AND its `.jr-error` sentence — and on this screen that
   sentence is the ONLY place a field refusal is ever drawn, because `validation`
   maps to empty banner copy on purpose. Hiding it therefore hid the reason and
   left the visitor pressing a button that kept answering the same way.
   ⚖️ The `:not(:has())` pair is the smallest possible statement of "hide the
   shortcut, never the problem": the moment the server has something to say about
   this field the row comes back, tick or no tick. A browser too old for `:has()`
   shows both rows, which is R1's own ratified fallback. */
.jr-grp > .jr-sw:has(> input:checked) + .jr-gr:not(:has(.jr-error)):not(:has(.jr-warn)) { display: none; }

.jr-sw {
  display: flex; align-items: center; gap: 10px;
  min-height: 46px; padding: 8px 14px;
  font-family: inherit; font-weight: 400; font-size: 14px; line-height: 1.4; color: var(--jr-muted);
  background: var(--jr-quiet);
  border-block-start: 1.5px solid var(--jr-line-soft);
  cursor: pointer;
}
.jr-sw input { width: 20px; height: 20px; flex: 0 0 auto; }
.jr-sw__text { min-width: 0; }

/* --- a row inside a group that is a statement, not a field ---------------- */
.jr-li { display: flex; align-items: center; gap: 11px; padding: 11px 14px; border-block-start: 1.5px solid var(--jr-line-soft); }
.jr-grp > .jr-li:first-child { border-block-start: 0; }

/* --- the verification panel, restyled WITHOUT touching its markup ---------
   ⛔⭐ NOT ONE BYTE OF `partials/verify_panel.php` CHANGED, AND THAT WAS THE
   DESIGN CONSTRAINT RATHER THAN A CONVENIENCE. `campaign_lead_verify_endpoint_gate`
   §6 freezes that file by SUBSTRING COUNT — one `<form class="jr-vform">`, one
   `<form class="jr-cpref">`, exactly four `type="submit"`, exactly two
   `clip-path:inset(50%)`, `</ul>` before the channel form, and more. Those counts
   are the panel's real contract (they are how "no nested form" and "no second
   send button" are proved), so the delivery's look had to be reachable from the
   class names that are already in the markup. It is: every rule below selects
   something the panel already emits.
   ⚖️ The rows therefore keep their vocabulary — `jr-vrow`, `jr-check-row`,
   `jr-vrow__say`, `jr-vrow__val` — and only their appearance moves. */

/* The list becomes the bordered group the delivery draws around the rows. */
.jr-verify__list {
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card); overflow: hidden;
}
.jr-vrow { padding: 0; }
.jr-vrow + .jr-vrow { border-block-start: 1.5px solid var(--jr-line-soft); }
.jr-vrow .jr-check-row { padding: 11px 14px; gap: 11px; }
/* ⭐ THE OPEN ROW IS THE ONLY TINTED THING ON THE SCREEN. One thing is being
   asked of the owner at a time, and this is how the eye finds it among rows
   that are already settled. The whole row, not just the mark. */
.jr-vrow--open { background: var(--jr-accent-tint); }
.jr-vrow--open .jr-vrow__say, .jr-vrow--open .jr-vform { padding-inline: 14px; }
.jr-vrow--open .jr-vform { padding-block-end: 12px; }
.jr-vrow--ok .jr-vrow__say { padding-inline: 14px; padding-block-end: 10px; }

/* The 10-pixel dot becomes the delivery's 22-pixel round mark. The tick is a
   CSS glyph on a span the markup already renders empty and `aria-hidden` — the
   words in the row are what a screen reader is told, exactly as before. */
.jr-check-row__mark {
  width: 22px; height: 22px; border-radius: 999px;
  display: grid; place-items: center;
  font-family: inherit; font-weight: 700; font-size: 12px; line-height: 1;
}
.jr-vrow--ok .jr-check-row__mark {
  background: var(--jr-green-soft); color: var(--jr-green-ink);
}
.jr-vrow--ok .jr-check-row__mark::before { content: "\2713"; }
/* An open row is a ring that breathes, never a red dot: nothing here is wrong,
   something here is simply still to do. */
.jr-vrow--open .jr-check-row__mark {
  background: none; border: 2px solid var(--jr-accent);
  animation: jr-logo-pulse 1.6s ease-in-out infinite;
}
/* ⚖️⭐ AND THE ROW IS NOT WRITTEN IN THE REFUSAL RED EITHER. `.jr-check-row--bad`
   is shared with the final check, where red is right because a criterion has
   FAILED; here the same class only means "not proved yet", which is the normal
   state of a screen the owner has just arrived on. Measured in a real browser:
   all three labels came out dark red on first load, which read as three errors
   on a form nobody had submitted. The label goes back to ordinary ink and the
   accent carries the "still to do" — the same colour as the button the owner is
   meant to press, which is exactly what this is. */
.jr-vrow--open .jr-check-row__text { color: var(--jr-ink); font-weight: 500; }
.jr-vrow--open .jr-vrow__state { color: var(--jr-accent-ink); }
/* ⛔ AND IT DOES NOT MOVE FOR SOMEBODY WHO ASKED FOR STILLNESS. */
@media (prefers-reduced-motion: reduce) {
  .jr-vrow--open .jr-check-row__mark { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   E2 · WHERE IS THE WORK ON THIS ROW? — the other seven states
   ══════════════════════════════════════════════════════════════════════════
   ⭐⭐ WELLE 1 DREW ONE OPEN STATE AND THE MODEL HAS SEVEN. Item 2 of the
   delivery's own Welle-2 order: "die neun Verify-Zeilenzustände inkl. `locked` /
   `spent` / `unreadable`". Until this batch, "press this button", "correct the
   typo in the form six centimetres above you" and "wait out a thirty-minute lock
   in which nothing you do has any effect" were the SAME pulsing accent ring, the
   same tinted ground and the same word — and two of the three offer no button at
   all, so the ring pulsed over a row with nothing on it.

   ⛔ THREE SHAPES, NOT SEVEN, AND THE QUESTION IS ABOUT THE CONTENT.
   campaign_lead_verify_state_mode() answers it: `do` (here), `fix` (in the form
   above), `wait` (not on this row at all). Not one rule below names a state.

   ⛔ AND THE THREE GROUNDS ARE THE THREE FAMILIES THIS BATCH MEASURED. They are
   painted next to each other inside one bordered list — which is exactly the
   place where the old amber and the old accent tint (ΔE 0.0114) would have been
   one colour with two names. See the palette. */

/* --- `do` — the work is here. Unchanged, and that is the point --------------
   ⛔ NOTHING ABOVE THIS COMMENT MOVED. `send` / `check` / `expired` are what the
   sixteen delivered screenshots show, and a batch that re-toned the ordinary
   case while adding the rare ones would make every one of them stale. */

/* --- `fix` — the work is in the form above --------------------------------
   The only state where the platform is holding a value it cannot use: a number
   it cannot read, or a country it cannot dial. No code can go to it, so there is
   no button, and `vf_fix` points UP at the input that holds it.
   ⭐⭐ SO IT WEARS THE FIELD'S OWN RED, and that is this batch's whole rule made
   visible in one place: red means a VALUE must change, and the value is on this
   screen. The row and the cell above it are now the same statement said twice —
   which is also why the page marks that cell (see index.php). */
.jr-vrow--fix { background: var(--jr-red-soft); }
.jr-vrow--fix .jr-check-row__mark {
  background: var(--jr-card); border: 2px solid var(--jr-red);
  color: var(--jr-red-ink);
  /* ⛔ AND IT DOES NOT PULSE. A ring that breathes says "something is happening
     here"; nothing is happening here until somebody edits a field. */
  animation: none;
}
/* 🔴 MEASURED, NOT GENERALISED — E1's ladder, one glyph and one size along.
   `!` spans from the baseline to the cap height, so `place-items: center` sets
   it correctly and it takes NO lift; the ellipsis two rules below sits ON the
   baseline and takes one. E1 measured 0.17 px for `!` and 7.00 px for `…` at
   26 px and wrote down that a blanket correction would move two right glyphs to
   rescue one wrong one. The same measurement was taken again at this mark's
   12 px before either rule was written. */
.jr-vrow--fix .jr-check-row__mark::before { content: "!"; }
.jr-vrow--fix .jr-vrow__state { color: var(--jr-red-ink); }
.jr-vrow--fix .jr-vrow__say { color: var(--jr-red-ink); }
/* ⭐⭐ F3 · OWNER DECISION 1 — AND NOW THE ROW HAS SOMETHING TO PRESS. `fix` is
   the one open state with no form, because no code can travel to a value we
   cannot read; its work is in the field a few centimetres higher, and until this
   batch the sentence said so without offering a way there. A LINK and not a
   button: it posts nothing, spends nothing and needs no credential — it moves
   the reader to an input on the page they are already on.
   ⚖️ IT WEARS THE ROW'S OWN RED, never the accent. Red on this journey means a
   VALUE has to change, which is the whole of what this link says; the accent is
   for "press this and something happens on the server".
   ⚠️ MARGIN, NOT PADDING, for the 14 px inset — the row's ground is the `<li>`,
   so the underline must be as wide as the words and not as wide as the box. */
.jr-vfix {
  display: inline-block; margin: 6px 14px 12px;
  font-family: inherit; font-weight: 600; font-size: 13px; line-height: 1.4;
  color: var(--jr-red-ink); text-decoration: underline; text-underline-offset: 3px;
}
.jr-vfix:focus-visible { outline: 2px solid oklch(0.45 0.09 250); outline-offset: 2px; }

/* --- `wait` — the work is not on this row at all ---------------------------
   A lock running out (`locked`), a budget that renews tomorrow (`spent`), or the
   row above settling this one too (`twin`). Amber, which on this platform has
   always meant "look at this" and never "this failed" — and nothing pulses,
   because nothing on this line is going to happen. */
.jr-vrow--wait { background: var(--jr-amber-soft); }
.jr-vrow--wait .jr-check-row__mark {
  background: var(--jr-card); border: 2px solid var(--jr-amber-line);
  color: var(--jr-amber-ink);
  animation: none;
}
/* 🔴🔴 AND THIS ONE DOES TAKE THE LIFT. `\2026` is a thin band of ink ON the
   baseline: centring its BOX leaves its INK low, which is the defect E1 walked a
   ladder for on the 26-px notice mark. The offset is expressed in `em` so it
   scales with the glyph, and it was re-measured at this mark's own 12 px rather
   than carried over as a number. */
.jr-vrow--wait .jr-check-row__mark::before { content: "\2026"; position: relative; top: -.27em; }
.jr-vrow--wait .jr-vrow__state { color: var(--jr-amber-ink); }
.jr-vrow--wait .jr-vrow__say { color: var(--jr-amber-ink); }
/* The two lines the locked row now carries sit in its own ink, not in the muted
   grey of a row that is merely open. */
.jr-vrow--wait .jr-vrow__again { color: var(--jr-amber-ink); }
.jr-vrow--wait .jr-vrow__at,
.jr-vrow--wait .jr-vrow__deadline { color: var(--jr-amber-ink); }
/* The code and its button on one line, wrapping together on a narrow phone. */
.jr-vform { align-items: stretch; }
.jr-vcode { min-height: 48px; font: 700 19px/1 var(--jr-mono); letter-spacing: .18em; text-align: center; }

/* --- the channel question as one segmented control ------------------------
   ⭐ STILL TWO SUBMIT BUTTONS, not the prototype's two radios. One tap is the
   whole interaction and it works with no JavaScript at all, which a radio
   cannot do without a third control to send it. `aria-pressed` still says which
   one is in force — now marked by ground, ink AND weight, so it survives a
   colour-blind reader and a printed page. Markup untouched. */
.jr-cpref__opts {
  gap: 3px; padding: 3px;
  border-radius: var(--jr-radius-sm); background: var(--jr-line-soft);
}
/* ⚖️ 28.08 abends (owner): the INLINE pair (answer already saved) grows to the same
   64px as the overlay's, and lays out as a wrapping row — icon · word · „Empfohlen" —
   so the badge takes its own line on a phone instead of squeezing the word. The
   segmented look (ground, radius, pressed state) stays exactly as it was. */
.jr-cpref__opts .jr-vbtn {
  flex: 1 1 0; min-width: 0; min-height: 64px; padding: 8px 10px;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px 8px;
  border: 0; border-radius: 10px; background: transparent;
  font-family: inherit; font-weight: 600; font-size: 14.5px; line-height: 1.25; color: var(--jr-muted);
}
.jr-cpref__opts .jr-vbtn .jr-cpref__ico { margin-inline-end: 0; vertical-align: middle; }
.jr-cpref__opts .jr-vbtn--reco::after { margin-inline-start: 0; white-space: nowrap; }
.jr-cpref .jr-vbtn[aria-pressed="true"] {
  background: var(--jr-card); color: var(--jr-ink);
  box-shadow: 0 2px 8px rgba(24, 32, 72, .1);
}

/* --- the closed gate, said in the footer ---------------------------------
   ⚖️ NOT AN ERROR AND NOT STYLED AS ONE. `vf_gate` states a condition of the
   journey ("telephone and e-mail have to be proven"), which is true from the
   moment the screen is drawn and is nobody's mistake. It gets the muted ink of
   an ordinary hint, never `--jr-red`; the panel above is what says what to do. */
.jr-foot__gate { margin: 9px 0 0; font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-muted); text-align: center; }
.jr-foot__link { color: var(--jr-accent-ink); text-decoration: underline; text-underline-offset: 3px; }
/* ⭐⭐ REDUCED PROMINENCE LIVES ON THE FOOTER, NOT ON THE BUTTON — and that is
   load-bearing rather than tidy. `journey_view_gate.php:620` freezes the exact
   single-spaced string `class="jr-cta" type="submit" form="jr-form"` on this
   screen, and `journey_visual_gate.js` finds the primary action with the
   selector `button.jr-cta`. Writing the quiet variant onto the button would
   have moved both for a change that is purely about ink.
   ⚖️ AND THE BUTTON STAYS A SUBMIT. The delivery's own `basisdaten` screen
   carries no master-data form at all, which is why its footer can be a bare
   anchor; ours does carry one, and V5's contract for this station is
   "Speichern geht immer, Verlassen erst mit bewiesenem Telefon und E-Mail".
   Turning the one control into a link would have deleted the only way to
   correct a mistyped address while the gate is shut. So the anchor is added
   beside the button and the button loses its loudness. */
.jr-foot--gated .jr-cta {
  background: var(--jr-card); color: var(--jr-ink);
  border: 1.5px solid var(--jr-line); box-shadow: none; font-weight: 600;
}
.jr-foot--gated .jr-cta:hover { background: var(--jr-quiet); border-color: var(--jr-line-strong); }

/* ══════════════════════════════════════════════════════════════════════════
   D4 — STATION 3 (logo) AND STATION 4 (zeiten_dienste)
   ══════════════════════════════════════════════════════════════════════════
   The same rule as D3: every colour, radius and pixel below stands in
   `reise.dc.html`. Adaptations are marked ⚠️ at the rule and each has one of
   three reasons — five languages instead of one, a thumb instead of a mouse,
   or a browser with scripting off, which the prototype never has to survive.
   ⛔ AND NOT ONE NEW `font:` SHORTHAND WITH `inherit` IN IT. D3 found 57 of
   them dead — `inherit` is a CSS-wide keyword and is not allowed in the family
   slot of the shorthand, so the whole declaration is thrown away and the
   control renders in 13.33 px Arial. Every rule here writes
   `font-family: inherit` in full. */

/* --- the upload: one dashed card, and the control INSIDE it ---------------
   The delivery draws a dashed 16-px card with an arrow, a bold line and a
   quiet one, and hides the file input with `left: -9999px`.
   🔴 THAT OFFSET IS THE ONE THING ON THIS SCREEN WE MAY NOT COPY. W1 measured
   it: a negative inline offset EXTENDS the scrollable area of a right-to-left
   document, and the Arabic form came back 10 389 px wide against a 390-px
   viewport. `journey_visual_gate.js` now fails a whole run on it. So the input
   is clipped exactly the way the honeypots are — still rendered, still
   focusable, still in the accessibility tree, and zero pixels wide. */
.jr-drop {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 22px 16px; text-align: center; cursor: pointer;
  border: 1.5px dashed var(--jr-line-strong); border-radius: 16px;
  background: var(--jr-quiet);
}
.jr-drop__icon { flex: 0 0 auto; color: var(--jr-accent); }
.jr-drop__t { font-family: inherit; font-weight: 700; font-size: 15.5px; line-height: 1.3; color: var(--jr-ink); }
/* ⚠️ 34ch is the delivery's own measure; `overflow-wrap` is the five-language
   floor D3 learned to put under every width it pins by hand. */
.jr-drop__s { max-width: 34ch; font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-label); overflow-wrap: anywhere; }
/* ⭐ D7 · AND THIS ONE GEOMETRY NOW SERVES BOTH OF ITS CONSUMERS. W1 wrote it for
   the file input above; D5 wrote the same ten declarations a second time, under
   the name `.jr-live`, for the live regions of the waiting screens — and that
   name already meant something else (D6 §4, and the section at the foot of this
   file). The three live regions wear `.jr-clip` since D7 and the duplicate is
   gone: one geometry, one name, two kinds of element.
   ⛔ WHAT IT MUST NEVER BECOME IS `display: none` OR `[hidden]`. Both take an
   element out of the accessibility tree, and one of the two consumers is an
   `aria-live` region — a live region nothing can read announces nothing. Hiding
   by clipping is the only way to hide something that still has to speak.
   ⚠️ `margin: 0` IS LOAD-BEARING for the second consumer: a `<p>` carries `1em`
   of user-agent margin top and bottom, and a one-pixel box with 16 px of margin
   around it pushes the rest of the screen down by 32 px. */
.jr-clip {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* ⚠️ A KEYBOARD MUST SEE WHERE IT IS. The input is one pixel wide, so the ring
   has to be drawn by the card that stands for it. */
.jr-field:focus-within > .jr-drop { border-color: var(--jr-accent); border-style: solid; box-shadow: 0 0 0 4px rgba(236, 48, 19, .12); }
.jr-drop:hover { border-color: var(--jr-accent); }
/* A local selection, not a server success. The preview is the evidence that
   the picker worked; the quiet copy says the upload still waits for next. */
.jr-logo-picked:not([hidden]) {
  display: flex; align-items: center; gap: 12px; margin-top: 12px; padding: 12px;
  border: 1px solid var(--jr-field); border-radius: 14px; background: #fff;
}
.jr-logo-picked__img {
  width: 72px; height: 72px; flex: 0 0 72px; object-fit: contain;
  border: 1px solid var(--jr-line-strong); border-radius: 10px; background: var(--jr-quiet);
}
.jr-logo-picked__body { display: flex; flex: 1 1 auto; min-width: 0; flex-direction: column; gap: 3px; }
.jr-logo-picked__name {
  font-family: inherit; font-weight: 700; font-size: 14px; line-height: 1.35;
  color: var(--jr-ink); overflow-wrap: anywhere;
}
.jr-logo-picked__note {
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.45;
  color: var(--jr-muted);
}
/* What `jr-logo-shrink.js` says once it has done the work — hidden until it
   has. ⛔ THE TEXT IS SERVER-RENDERED AND THE SCRIPT ONLY REVEALS IT:
   `public-i18n.js` walks `[data-i18n]` once and offers no event a later script
   can fire, so a sentence written BY JavaScript would be a sentence in no
   language at all. */
.jr-said {
  display: flex; gap: 8px; align-items: flex-start; margin: 10px 0 0;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-green-ink);
}
/* 🔴 AND `hidden` HAS TO BE SAID AGAIN, because `display: flex` above already
   beat it. The `[hidden] { display: none }` that browsers ship lives in the USER
   AGENT stylesheet, which loses to any author declaration whatsoever — so the
   line above silently un-hid the one sentence on this screen that is only true
   after a script has done some work. Caught in a screenshot, which is the only
   place it was visible: the markup said `hidden` and the eye said otherwise. */
.jr-said[hidden] { display: none; }
/* 🔴 F1 · THE GREEN DOT IS DELETED WITH ITS MARKUP — "eine Meldung, keine
   Errungenschaft". Green is this journey's word for a completed act, and a
   report about a resized file is not one. The rule goes with the element rather
   than staying behind as a class nothing sets. */

/* --- F1 · a caption: a sentence that labels what stands ABOVE it ----------
   ⭐ THE THIRD DIRECTION OF THE SAME TYPE SIZE. `.jr-hint` precedes what it is
   about and pays its margin downwards; `.jr-fine` is small print underneath;
   this is a caption — one step larger than small print, because it is an
   INSTRUCTION about the row of controls it follows ("Einen auswählen" under the
   four logo marks) and not a subordinate clause. The delivery's own values. */
.jr-caption {
  margin: 14px 0 0;
  font-family: inherit; font-weight: 400; font-size: 13.5px; line-height: 1.45;
  color: var(--jr-muted);
}
.jr-caption[data-i18n="journey.l_ai_note"] {
  margin-bottom: 20px;
}

/* --- "oder": a word between two rules ------------------------------------
   🔴 OWNER, 21.08.2026 — THE RULE MUST NOT PINCH EITHER DOOR. On the stacked
   composition the doors are above and below it, so the breathing room is
   block-axis margin. In the wide composition below the rule turns vertical and
   the same promise moves to logical inline padding. Logical axes keep Arabic
   identical without a left/right override. */
.jr-or { display: flex; align-items: center; gap: 12px; margin: 20px 0; }
.jr-or::before, .jr-or::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--jr-line); }
.jr-or__t { flex: 0 0 auto; font-family: inherit; font-weight: 600; font-size: 12px; line-height: 1.3; color: var(--jr-faint); }

/* --- how many attempts are left ------------------------------------------
   🔴 29.08.2026 · DIE DREI REGELN SIND FORT, WEIL DER SATZ FORT IST.
   Hier standen `.jr-tries`, `.jr-tries__n` und `.jr-tries__t` für «1 Versuche
   übrig». Der Inhaber hat den Satz abgeschafft — bei EINEM Versuch sagt ein
   Zähler nichts, was das Vorhandensein des Knopfes nicht schon sagt.
   ⛔ Und sie werden nicht „für später" stehen gelassen: eine Regel ohne Auslieferung
   ist genau das tote Gewicht, das beim nächsten Umbau als Wahrheit gelesen wird.
   Die Zahl selbst lebt weiter als `data-jr-logo-tries` auf `section.jr-logo-ai`
   — maschinenlesbar, ohne Farbe und ohne Fläche. */

/* --- the segmented control ------------------------------------------------
   The delivery's `.seg`: a tinted trough in which the chosen answer is a white
   card. ⚠️ THE SERVER STILL WRITES THE STATE. `:has(input:checked)` keeps the
   pill correct after a click that has not been submitted yet; `--on` is what
   the page renders from the stored plan, so an engine without `:has()` shows
   the delivery's design rather than a control with no answer in it. */
.jr-seg { display: flex; gap: 3px; padding: 3px; border-radius: 12px; background: var(--jr-line-soft); }
.jr-seg__opt {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  /* ⚠️ 44 AND NOT THE DELIVERY'S 42. Measured in a real browser: the trough
     around it is 48 px tall, but the thing a thumb actually hits is the label,
     and 42 is under the floor this journey holds every control to. Two pixels,
     and the row grows by two. */
  min-height: 44px; padding: 0 6px; border-radius: 10px;
  font-family: inherit; font-weight: 600; font-size: 14.5px; line-height: 1.25; text-align: center;
  color: var(--jr-muted); cursor: pointer;
}
.jr-seg__opt > span { min-width: 0; overflow-wrap: anywhere; }
/* ⚖️ 24.08.2026 (owner) · «حط هون ايقونات توصيل و استلام احترافية» — the
   service glyphs on the offer tabs and the week headings. The tab is already a
   centred flex row with its own gap, so the icon only brings its size and
   inherits the tab's ink through currentColor — active and idle alike. */
.jr-seg__icon, .jr-wkh__icon {
  flex: 0 0 auto; display: inline-flex;
  inline-size: 17px; block-size: 17px;
}
.jr-seg__icon > svg, .jr-wkh__icon > svg { inline-size: 100%; block-size: 100%; }
/* the week heading becomes a pair inside its own grid cell */
.jr-wkh__t { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
/* 🪤 the scooter reads in a direction — the recorded toggles-mirror rule,
   applied to a picture: under RTL it rides the other way. Keyed on the svg's
   own attribute, never on a modifier class (the class census counts subjects). */
[dir="rtl"] svg[data-jr-flip] { transform: scaleX(-1); }
.jr-seg__opt--on, .jr-seg__opt:has(input:checked) {
  background: var(--jr-card); color: var(--jr-ink);
  box-shadow: 0 2px 8px rgba(24, 32, 72, .1);
}
.jr-seg__opt:has(input:focus-visible) { outline: 2px solid var(--jr-accent); outline-offset: 2px; }

/* --- the week: one grid, four columns -------------------------------------
   The delivery's `.wk`: `clamp(40px, 20%, 84px) 1fr 1fr 34px`, 8-px gaps, one
   row per day inside the bordered group. */
.jr-wk { container-type: inline-size; }
.jr-wkr {
  display: grid; grid-template-columns: clamp(44px, 20%, 96px) minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 8px; align-items: center;
  padding: 7px 14px; border-block-start: 1.5px solid var(--jr-line-soft);
}
.jr-wk > .jr-wkr:first-child, .jr-wk > .jr-wkd:first-child > .jr-wkr:first-child { border-block-start: 0; }
.jr-wkr--head { background: var(--jr-quiet); }
.jr-wkr--head .jr-gl { padding-block-start: 0; }
.jr-wkr__d { min-width: 0; font-family: inherit; font-weight: 700; font-size: 13px; line-height: 1.35; overflow-wrap: anywhere; }
/* ⚠️ THE CELL IS THE TAP TARGET, NOT THE BOX WITH THE CARET — D3's measured
   correction, on a control that really is small. 44 px of row, and the input
   fills every pixel of it. */
.jr-wkr__t {
  width: 100%; box-sizing: border-box; min-width: 0; min-height: 44px; padding: 0 8px;
  border-radius: 11px; border: 1px solid var(--jr-field); background: var(--jr-card);
  color: var(--jr-ink);
  font-family: var(--jr-mono); font-weight: 400; font-size: 15px; line-height: 1;
  -webkit-appearance: none; appearance: none;
}
.jr-wkr__t:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 2px; }
/* The fourth column: whether the day counts at all. */
.jr-wko { display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; cursor: pointer; }
.jr-wko input { width: 20px; height: 20px; flex: 0 0 auto; }
.jr-wko__t { min-width: 0; font-family: inherit; font-weight: 500; font-size: 12px; line-height: 1.3; color: var(--jr-label); overflow-wrap: anywhere; }
/* ── 23.08.2026 · OWNER — A DAY'S STATE IS VISIBLE ON THE ROW ──────────────
   > «بس يتم تحديد الشيك بوكس المفروض يصير هذا اليوم … بس مافي شيء عم يظهر
   >  هذا الشيء ب اليو اي — اعمل هذا اليوم … بطريقة معينة»

   ⚠️ AND THE TICK MEANS **OPEN**, NOT CLOSED. The input is `[active]`, the column
   heading is `offen`, and the partial records why the prototype's polarity was
   inverted: an unticked box sends nothing, so a box meaning "closed" could never
   say so. A ticked day is a day the restaurant is OPEN.

   ⛔ AND NOT ONE WORD IS ADDED, WHICH IS ALSO A RECORDED DECISION.
   `journey_stations_gate.php` asserts that `z_closed` never reaches this form —
   "a form states the fact through its control's own state, and printing it
   beside an unticked checkbox would be the label the delivery deliberately made
   a column heading". So the state is said in ground and ink, exactly as that
   decision asks, and the review screen keeps the only word.

   ⚖️ THE OPEN DAY IS THE ONE THAT IS MARKED, AND THAT DIRECTION IS DELIBERATE.
   Greying the unticked rows would paint the ENTIRE week on a first visit — every
   day starts unticked — so an owner would meet a form that looks switched off and
   is asked to type into it. Marking the affirmative state instead leaves a fresh
   week neutral and lights each day as it is turned on.
   ⛔ THE FIELDS KEEP THEIR OWN WHITE GROUND (`.jr-wkr__t`), so nothing here can
   read as disabled: the tint is the row's, never the control's. */
/* ⚖️ OWNER, 24.08.2026, MINUTES AFTER THE GREEN TICK LANDED: «خضر كل شي مو بس
   الشيك بوكس» — the WHOLE open-day treatment speaks green now: the row's
   ground, the day's ink and the tick's own focus ring, all from the one green
   family the verify rows and the success window already speak. The direction
   of the marking (open = lit, fresh week = neutral) is untouched. */
.jr-wkd:has(.jr-wko input:checked) { background: var(--jr-green-soft); }
.jr-wkd:has(.jr-wko input:checked) .jr-wkr__d { color: var(--jr-green-ink); }
/* (the tick's own focus ring turns green beside the H2 block that draws it —
   the shared accent rule lives there and later in the sheet would win here) */

/* ── …AND A DAY THAT IS SHUT HAS NOTHING TO SAY ABOUT TIME ─────────────────
   > «اذا معنا مفتوح معناها لازم كل شيء ما عليه شيك بوكس يكون محظور»
   The fields of an unticked day are blocked, and `jr-hours-open.js` is the only
   thing that writes the attribute — never the server. A new week opens NO day
   (R1: an auto-seeded week is a claim nobody made), so a server-rendered
   `disabled` would meet a first visit with fourteen dead rows and no way to type
   an hour with scripting off. ⇒ With a script the day switches; without one the
   form is exactly as usable as it was, and the tint above still tells the state.
   ⛔ THE INK, NOT THE UA's GREY: browsers disagree about what a disabled
   `<input type="time">` looks like, and one of them keeps it black. */
.jr-wkr__t:disabled {
  background: var(--jr-quiet);
  color: var(--jr-disabled);
  border-color: var(--jr-line-soft);
  cursor: not-allowed;
}
.jr-wkd--shut .jr-wkm__s { opacity: .45; cursor: not-allowed; }

/* The second window, still a native disclosure — see the partial. */
.jr-wkm { border-block-start: 1.5px solid var(--jr-line-soft); }
.jr-wkm__s { list-style: none; padding: 8px 14px; font-family: inherit; font-weight: 500; font-size: 12px; line-height: 1.4; color: var(--jr-faint); cursor: pointer; }
.jr-wkm__s::-webkit-details-marker { display: none; }
.jr-wkm__s:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: -2px; }
.jr-wkm > .jr-wkr { border-block-start: 0; padding-block-start: 0; }
/* The second window carries only its two times; on a wide row they stand under
   the two columns they belong to rather than sliding into the day's place. */
.jr-wkr--w2 > .jr-wkr__f { grid-column: 2; }
.jr-wkr--w2 > .jr-wkr__to { grid-column: 3; }
/* The header's own cells, named rather than counted: an `<h2>` and three
   `<span>`s in one row make `nth-of-type` mean something other than "the third
   cell", which is how a layout starts lying about which column it is in. */
.jr-wkh__o { text-align: center; }
/* ⚠️ AND ON A PHONE THE ROW IS TWO LINES — measured, not preferred. Two
   `<input type="time">` need about 96 px each before Chromium begins cutting
   its own digits, and NO clipping test can see that: an input never reports
   `scrollWidth > clientWidth`, which is the same blindness that let D3 ship a
   truncated `<select>` twice. A 390-px phone leaves about 306 px inside the
   group; a day name, two of those and the checkbox do not fit on one line in
   any of the five languages.
   ⛔ AND THE QUESTION IS ABOUT THE GROUP, NOT THE WINDOW (D3's container-query
   lesson): the same week sits in a 306-px card on a phone and in a 700-px
   column on a desktop, and only the group knows which. */
@container (max-width: 400px) {
  .jr-wkr {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "d o" "f t";
    row-gap: 6px;
  }
  .jr-wkr > .jr-wkr__d, .jr-wkr > .jr-wkh__t { grid-area: d; }
  .jr-wkr > .jr-wkr__f, .jr-wkr > .jr-wkh__f { grid-area: f; }
  .jr-wkr > .jr-wkr__to, .jr-wkr > .jr-wkh__to { grid-area: t; }
  .jr-wkr > .jr-wko, .jr-wkr > .jr-wkh__o { grid-area: o; justify-content: flex-end; }
  /* The second window has no day and no checkbox of its own — it inherits the
     row above. Two cells, two halves, no empty first line. */
  .jr-wkr--w2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "f t"; }
  /* ⭐ 23.08.2026 · AND THE ✕ RIDES THE SAME TWO HALVES. On a narrow card the day
     row is `d o / f t`; the open second window is the same shape with the ✕ where
     the checkbox sits, so the two rows still read as one day. `display: contents`
     is undone here on purpose — this grid has areas, not four columns. */
  /* ⭐ 23.08.2026 · NARROW — the day row here is `d o / f t`, two halves, and the
     second window is the same two halves. There is no fourth column to borrow, so
     the four-column override above is undone and the ✕ keeps its place at the end
     of the row, clear of the two fields. */
  .jr-wkm[open] > .jr-wkr--w2 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    padding-inline-end: 40px;
  }
}

/* --- what `jr-hours-precheck.js` writes at the field ----------------------
   ⛔ CHIPS, NEVER A SENTENCE — the same rule the server's own issue list obeys,
   and the reason the "where" is a list of independent keys. */
.jr-fe { margin: 6px 0 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.jr-fe__what { min-width: 0; font-family: inherit; font-weight: 500; font-size: 12.5px; line-height: 1.4; color: var(--jr-red-ink); overflow-wrap: anywhere; }
.jr-wkr__t[aria-invalid="true"], .jr-gi[aria-invalid="true"] { border-color: var(--jr-red); }
.jr-wkr > .jr-fe { grid-column: 1 / -1; }
/* ⭐ N12 · 27.08.2026 — AND THE SAME SENTENCE ON A BLOCK.
   `no_open_day` and `delivery_pricing` are facts about a whole week or a whole
   price list; hanging them on Monday's first cell drew a red frame around a day
   the rule never asked for. The block placement gets breathing room above and
   below because it sits between a heading and a table rather than under a
   field — ⛔ and it borrows the SAME ink and the SAME chips, so the two
   placements read as one voice. */
.jr-fe--block { margin: 0 0 12px; }
.jr-hmsg { display: none; }

/* --- the default-hours card and the price list ----------------------------
   ⚖️ THE QUESTION IS NOT A WARNING. `z_seed_t`/`z_seed` ask the owner to confirm
   that the seeded week is really theirs; the amber family in this file is marked
   as the one thing the delivery has NOT drawn yet, and the prototype paints a
   question in the accent tint (`#fff8f6` / `#ffd9d1` — both already tokens
   here). One borrowed colour fewer. */
.jr-card--ask { border-color: var(--jr-accent-line); background: var(--jr-accent-tint); }
.jr-seed { margin-top: 12px; }
.jr-seed .jr-check { min-height: 44px; align-items: center; }
.jr-pricerow + .jr-pricerow { margin-top: 10px; }
/* --- F1 · "one row per click", with the only element a browser opens itself -
   ⭐ THE DISCLOSURES NEST, one per remaining blank row, so a press costs exactly
   one postcode line instead of dropping three empty ones onto the screen at once
   (R1 · Teil B, zeiten). Each level holds a row and, under it, the same offer
   again — which is the gesture a script would give, without a script.
   ⚠️ THE GAP IS THE SUMMARY'S, NOT THE ROW'S. A `<details>` is a plain block
   with no margin of its own, and its `<summary>` already carries `margin-top`
   from `.jr-more--sm`; the row inside it needs the same rhythm the sibling rows
   have, which `.jr-pricerow + .jr-pricerow` cannot give it across the element
   boundary. */
.jr-morerow > .jr-pricerow { margin-top: 10px; }

/* ══════════════════════════════════════════════════════════════════════════
   D4 — what the width is FOR on these two screens
   ══════════════════════════════════════════════════════════════════════════
   D3 granted `--wide` (460 · 820 from 834 · 1120 from 1280) and made it opt-in
   per screen, because a wide shell around pre-design markup is worse than a
   centred phone column. These two screens now have somewhere to put it.
   ⚖️ AND NOT MORE THAN THAT. The delivery's own README defers the desktop
   BREAK-OUT of the week plan to Welle 2 (§"Was ich für Welle 2 vorschlage", 6).
   What is here is the width being USED — the day row stops folding, the four
   proposals go across in one line, the two service weeks stand side by side —
   and not a second desktop design of the station. */
@media (min-width: 834px) {
  /* Upload on the left, "have one drawn" on the right, the word between them.
     ⛔ ONLY WHEN THERE IS A SECOND SIDE: the generate half is absent while an
     attempt runs and once the quota is spent, so `:has()` asks instead of
     assuming — D3's `:has(> .jr-verify)` lesson, which was measured on a
     desktop screenshot after a rule keyed on the station name gave the entry
     form a second column with nothing in it. */
  .jr-shell--wide .jr-logo-two:has(> .jr-or) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(72px, 8.75vw, 112px) minmax(0, 1fr);
    gap: 4px; align-items: start;
  }
  /* 🔴 OWNER FOLLOW-UP, REPEATED 22.08.2026 — PADDING ALONE STILL LEFT THE
     GUTTER LANGUAGE-DEPENDENT: Arabic's short «أو» made the auto track sixteen
     pixels narrower than oder / veya. The middle TRACK now owns the whole
     gutter, so both doors sit equally far from the rule in every language:
     about 40 px each at 834 and 60 px each from the 1280 breakpoint onward.
     This is also the largest measured track that keeps both tablet doors above
     334 px and both desktop doors above 474 px. */
  .jr-shell--wide .jr-logo-two:has(> .jr-or) > .jr-or {
    flex-direction: column; inline-size: 100%; margin: 0; padding-inline: 0; align-self: stretch;
  }
  .jr-shell--wide .jr-logo-two:has(> .jr-or) > .jr-or::before,
  .jr-shell--wide .jr-logo-two:has(> .jr-or) > .jr-or::after { width: 1px; height: auto; }
}
/* ══════════════════════════════════════════════════════════════════════════
   E2 · THE WEEK'S DESKTOP BREAK-OUT — and the tablet was the worst of the three
   ══════════════════════════════════════════════════════════════════════════
   ⭐ D4 BUILT THIS AND PUT IT AT 1280. Item 6 of the delivery's Welle-2 order is
   "Desktop-Ausbrüche für Wochenplan und Startliste", and half of the week's was
   already standing: from 1280 the two service weeks are side by side, which is
   the comparison the two weeks are kept apart FOR.

   🔴 WHAT THE MEASUREMENT FOUND IS THAT THE TABLET WAS WORSE THAN THE PHONE.
   Between 834 and 1279 the shell widens to 794 px, the two weeks stay stacked,
   and the day row divides that width by its own template — so an
   `<input type="time">` holding four digits and a colon came out **288 px wide**,
   against 147 on a phone and 177 on a desktop. Fourteen of them, twice, down a
   2184-px page. That is the "stretched instead of laid out" shape D7 named on the
   other screen in this item, and it is invisible to every clipping test, because
   an input never reports `scrollWidth > clientWidth` (D3's recorded blindness).

   ⇒ THE BREAK-OUT STARTS WHERE THE WIDTH DOES. The same rule, one breakpoint
   earlier: at 834 each week gets ~367 px, which puts the day row back into the
   compact two-line form the container query already defines for a phone-sized
   group — a shape that has been measured in five languages since D4 — and it
   halves the page. Nothing new is invented; the width simply stops being spent
   on the inside of a time field. */
@media (min-width: 834px) {
  /* Two weeks side by side — a restaurant that collects until 22:00 and stops
     delivering at 21:00 sees both at once instead of scrolling between them.
     That comparison is the entire reason the two weeks are kept apart. */
  .jr-shell--wide .jr-weeks { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
  .jr-shell--wide .jr-weeks > .jr-block { margin-bottom: 0; }
}

/* ══════════════════════════════════════════════════════════════════════════
   D5 — the middle of the journey: check, agree, and the screens you wait on
   ══════════════════════════════════════════════════════════════════════════
   Four screens, one vocabulary. Every colour, radius and weight below already
   stands in `reise.dc.html`; the ⚠️ marks are the places where five languages or
   a measured fact made the delivery's own value wrong for us, and each says
   which.

   ⛔ NOT ONE RULE ASKS FOR A STATION BY NAME OR FOR A SHARED ID. D4 shipped
   `.jr-shell--wide #jr-form` keyed on an id and it broke the day a second screen
   carried that id. Everything below asks about CONTENT — "is there a second
   column's worth of tiles", "are there enough rows to split" — which is a
   question a screen can answer about itself.

   ⛔ AND EVERY TYPE RULE IS THREE LONGHANDS PLUS `font-family: inherit`. D3
   measured what the `font:` shorthand with `inherit` in it does: nothing, and it
   killed fifty-seven rules in silence. */

/* --- station 5 · the review, as tiles -------------------------------------
   ⭐ THE GRID IS THE WHOLE DESKTOP LAYOUT AND IT NEEDS NO WIDTH RULE AT ALL:
   `auto-fit` + `minmax` is content-driven by construction, so one column on a
   phone becomes two on a tablet and three on a desktop because the tiles
   themselves ran out of room — never because a media query was told which
   station this is. */
/* ⚖️ OWNER DECISION 23.08.2026 (N7) — ONE COLUMN, EVERY WIDTH. D5 made these
   three blocks an `auto-fit` grid so the browser decided how many fit; measured
   on the owner's own screen that produced a tall master-data card beside a
   nearly empty logo card, and the owner called it what it is: "شي حاوية كبيرة
   و شي صغيرة". Three cards of wildly different height are a worse summary
   than three full-width bands, because the eye has to find where each one ends.
   ⇒ stacked, each at the parent's full width, on desktop and tablet too. */
.jr-tiles { display: grid; grid-template-columns: 1fr; gap: 12px; align-items: start; }
.jr-review--tile {
  padding: 13px 14px; border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card); min-width: 0;
}
/* ⛔ THE STACK'S SEPARATOR MUST NOT REACH A TILE. `.jr-review` draws a hairline
   above itself and suppresses it on the first — right for a stack, a doubled
   line beside a border for a card. */
.jr-review--tile, .jr-review--tile:first-of-type { border-block-start: 1.5px solid var(--jr-line); padding-block-start: 13px; }
.jr-review--tile .jr-review__head { margin-bottom: 6px; }
/* The block label is the delivery's `gl`: small, quiet, and never competing with
   the headline of the page it sits on. */
.jr-review--tile .jr-h2 {
  font-family: inherit; font-weight: 700; font-size: 11.5px; line-height: 1.3;
  letter-spacing: .08em; text-transform: uppercase; color: var(--jr-label);
}
/* ⚠️ ARABIC KEEPS ITS LETTERS. `letter-spacing` on an Arabic string breaks the
   joins and clips the descenders — measured on this platform before, and the
   reason the rule above is undone rather than written twice. */
body.jr-page[dir="rtl"] .jr-review--tile .jr-h2 { letter-spacing: 0; text-transform: none; }
/* ⚠️ THE VALUES ALIGN ACROSS ROWS, and that is why `.jr-kv` becomes a grid
   PARTICIPANT rather than a grid of its own: a per-row `grid-template-columns`
   restarts the measure on every line and nine labels step down the tile. The
   markup does not change — `display: contents` lets the two spans the partial
   already renders become cells of the enclosing grid — and where it is not
   supported the rule simply does not apply and each pair stays the flex row it
   already was, which is a readable fallback rather than a broken one. */
.jr-facts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 3px 12px; align-items: baseline; }
.jr-facts > .jr-kv { display: contents; }
.jr-facts > .jr-kv > .jr-kv__k { font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.35; }
.jr-facts > .jr-kv > .jr-kv__v { font: 600 13px/1.4 var(--jr-mono); overflow-wrap: anywhere; }
/* Inside a tile the week is a list of days, not a table: one line per open day,
   the day name in the label column and its windows beside it. */
.jr-review--tile .jr-review__plan { margin-top: 10px; }
.jr-review--tile .jr-hours { padding: 2px 0; gap: 8px; }
.jr-review--tile .jr-hours__day { min-width: 0; flex: 0 0 auto; }

/* --- station 6 · the verdict list ----------------------------------------
   ⚠️⚠️ THE SAME CLASS, THE OPPOSITE MEANING — and this is the one screen where
   that matters. `.jr-check-row--bad` HERE means A CRITERION IS NOT MET, and red
   is the correct colour for it: the row is the reason the journey stops. In the
   V4 confirmation panel the very same class means "not proven YET", which is no
   failure at all, and that block deliberately overrules the red further up this
   file. ⇒ Everything below is scoped to `.jr-checks--verdict`, so the stronger
   reading cannot leak into `.jr-vrow`. */
.jr-checks--verdict {
  gap: 0; border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card); overflow: hidden;
}
.jr-checks--verdict > .jr-check-row { padding: 11px 14px; border-block-start: 1px solid var(--jr-line-soft); }
.jr-checks--verdict > .jr-check-row:first-child { border-block-start: none; }
/* ⭐ THE MARK GROWS INTO THE DELIVERY'S DISC AND KEEPS ITS `aria-hidden`. The
   tick is a CSS glyph precisely because it must stay unreadable to a screen
   reader: the row is spoken by its sentence, in the reader's own language, and a
   bare "✓" in the accessibility tree would be a second, wordless claim. */
.jr-checks--verdict .jr-check-row__mark {
  width: 20px; height: 20px; border-radius: 999px;
  display: grid; place-items: center;
  font-family: inherit; font-weight: 700; font-size: 12px; line-height: 1;
}
.jr-checks--verdict .jr-check-row--ok .jr-check-row__mark { background: var(--jr-green-soft); color: var(--jr-green-ink); }
.jr-checks--verdict .jr-check-row--ok .jr-check-row__mark::before { content: "\2713"; }
.jr-checks--verdict .jr-check-row--bad .jr-check-row__mark { background: var(--jr-accent-soft); color: var(--jr-red-ink); }
.jr-checks--verdict .jr-check-row--bad .jr-check-row__mark::before { content: "\00D7"; }
.jr-checks--verdict .jr-check-row__text { font-family: inherit; font-weight: 400; font-size: 14.5px; line-height: 1.45; }
.jr-checks--verdict .jr-check-row--bad .jr-check-row__text { font-weight: 500; }
/* ── 🔴 K-1 · 30.08.2026 · OWNER — THE DOOR ON A FAILING ROW ──────────────────
   ⭐ IT INVENTS NOTHING. The element is `.jr-edit`, the review's own "Ändern"
   link, and it therefore already carries D5's 45-px tap box (`padding-block: 14px`
   with the matching negative margin, further down this file) — a correction link
   at the point of no return is exactly as pressable as the one on the review.
   ⛔ NO COLOUR OF ITS OWN. The row is already red; a red link inside it would be
   a second alarm about one fact, and `--jr-ink` is what makes the link read as
   the ACTION rather than as more of the complaint.
   ⚖️ `nowrap` because the sentence beside it wraps instead: `.jr-check-row__text`
   is `flex: 1 1 auto; min-width: 0`, so the long criteria ("Dieses Logo wird für
   Ihr Online-Restaurant verwendet") give way and the door never breaks in two —
   including inside the two-column grid above 834 px, where each column is half
   as wide. Direction-neutral: `gap` and logical properties only. */
.jr-checks--verdict .jr-check-row > .jr-edit { flex: 0 0 auto; white-space: nowrap; }

/* --- station 7 · the two acts --------------------------------------------
   The consent act's closing line — "a second button follows: the build". Quiet
   and centred, because it is a promise about the NEXT press rather than an
   instruction for this one. */
.jr-two-acts {
  margin: 12px 0 0; text-align: center;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-label);
}

/* --- station 8 · the build, as a building going up — on the clock (BAU-1 · 24.08.2026 · BAU-2 · 25.08.2026) ----
   ⚖️ OWNER, 24.08.2026 evening: «في خطوات انشاء عم تكون طويلة و خطوات سريعة
   جداً - حسيت بالملل … بدنا نخلي البناء يتم انشاءه بشكل انسيابي قطعة قطعة خلال
   الـ٥ دقايق … بغض النظر عن يلي عم بصير بالخلفية … الشعار حجمه صغير كتير على
   اللوحة!» — BAU-1's five scenes (the worker's stage, one attribute) are the
   FLOOR of this block; on top of it Claude Design's second delivery
   (bau-szene-2.dc.html, 25.08.2026 — _patches/bau2_delivery_20260825/) tells the
   same building as FIFTY-THREE pieces on the announced wait, the sign the width
   of the facade. ⚖️ The sentences follow the story now, not the worker — an
   owner decision that AMENDS D5/BAU-1's "no claim about time", recorded as such.

   ⭐⭐ EVERY RULE BELOW IS CLAUDE DESIGN'S. The contract is theirs:
     · `data-jr-bau-stage="1…6"` on the root — the server's, cumulative end
       states + the scene's ambient loop, and it needs no script and no `:has()`;
     · `data-jr-bau-story="1…5"` on the root — the scene BY THE CLOCK, set by
       jr-bau-story.js; once present, visibility comes from `.is-built` alone;
     · each piece `[data-jb-piece][data-jb-at]`: `.is-built` starts its entry,
       `.is-built.is-instant` is the end state at once (a reload mid-story);
     · `data-jr-bau-wait="1"` the idle loop at 100 % with the worker still
       going; `data-jr-bau-rush="1"` + `--jb-tempo` (an inline custom property,
       .2 in the hurry) — EVERY entry duration is `calc(Xs * var(--jb-tempo, 1))`;
     · the two "leaving" pieces (`s5-kran-ab-6`, `s5-raeumen-7`), the rope's
       hold-until-bolted and the logo slot use `:has()` (Baseline 2023): the
       script refuses to start the story where it is missing, and the floor
       above uses none of it.
   The tokens are this file's own `--jr-*` variables; the delivery's local
   copies are dropped (identical values, one definition). Departures from the
   delivered sheet, each with a reason:
     · the phase number and the scene sentence are NAMED spans
       (`.jr-bau-phase__n`, `.jr-bau-titel__s`) rather than bare `span` — the
       label word beside the number is a span too, and must stay visible;
     · the RTL mirror uses `body.jr-page[dir="rtl"]`, this file's selector for
       direction, on the STAGE SVG only (`> svg`) — the tap hand in the overlay
       is not a picture of the building;
     · hover is `--jr-accent-hover`, no `filter`; the spec board's demo class
       `.jr-bau-static` is not emitted by this journey and has no rule;
     · 🔴 `jb-fall` carries `opacity: 1` in its keyframes again — the delivery's
       version animated transform only, under a static `.jb-kf { opacity: 0 }`,
       so the scene-6 confetti would never have shown (BAU-1's fix, re-applied).
   🔴 `[hidden]` IS USED IN THE SCENE NOW — on the fifty-three action sentences,
   and only there — and `.jr-bau [hidden] { display: none !important; }` is what
   makes that safe against any author `display:` (N8-3, closed by construction).
   🔴 NO `inset-inline-start` + `translate(-50%)` (N8-9): both overlays are
   placed by logical inset and WIDTH. */
.jr-bau { --jb-tempo: 1; container-type: inline-size; display: block; background: var(--jr-card); color: var(--jr-ink); font: inherit; }
.jr-bau * { box-sizing: border-box; }
.jr-bau-innen { display: flex; flex-direction: column; gap: 14px; padding: 20px 18px 8px; }
.jr-bau-status { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; text-align: start; }
.jr-bau-phase { font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--jr-muted); white-space: nowrap; }
.jr-bau-phase__n { display: none; }
.jr-bau-titel { font-size: clamp(19px, 5.2cqi, 27px); font-weight: 800; line-height: 1.12; letter-spacing: -.01em; text-wrap: pretty; min-height: 2.25em; }
.jr-bau-titel__s { display: none; }
.jr-bau-sub { display: none; font-size: 14px; color: var(--jr-muted); }
.jr-bau-fertig { display: none; align-items: center; gap: 7px; padding: 6px 11px; background: var(--jr-green-soft); border: 1.5px solid var(--jr-green); color: var(--jr-green-ink); font-size: 12.5px; font-weight: 700; white-space: nowrap; }
/* Akt-Zeile: nur mit Zeit-Ebene sichtbar; alle Saetze im Markup, euer Skript schiebt [hidden] */
.jr-bau-akt { display: none; align-items: flex-start; gap: 8px; min-height: 2.5em; font-size: 13.5px; font-weight: 600; color: var(--jr-muted); line-height: 1.3; }
.jr-bau[data-jr-bau-story]:not([data-jr-bau-stage="6"]) .jr-bau-akt { display: flex; }
.jb-bullet { flex: none; width: 8px; height: 8px; margin-top: .28em; background: var(--jr-ink); animation: jb-bullet 1.3s ease-in-out infinite alternate; }
[data-jr-bau-wait="1"] .jb-bullet { animation-duration: 2.6s; }
.jr-bau-say { display: inline; animation: jb-satz .45s ease both; }
.jr-bau-ticks { display: flex; gap: 5px; margin-top: 2px; }
.jr-bau-tick { width: 22px; height: 7px; background: var(--jr-line); }
.jr-bau-tick.jb-on { background: var(--jr-ink); }
.jr-bau-tick.jb-cur { background: var(--jr-muted); animation: jb-tick 1.2s ease-in-out infinite alternate; }
[data-jr-bau-stage="6"] .jr-bau-tick { background: var(--jr-green); animation: none; }
[data-jr-bau-stage="6"] .jr-bau-sub { display: block; }
[data-jr-bau-stage="6"] .jr-bau-fertig { display: inline-flex; animation: jb-pop .5s .5s cubic-bezier(.2, .8, .3, 1.2) both; }
.jr-bau-buehne { position: relative; container-type: inline-size; flex: 1; min-width: 0; }
.jr-bau-buehne > svg { display: block; width: 100%; height: auto; }
@container (min-width: 640px) {
  .jr-bau-innen { flex-direction: row; align-items: center; gap: 30px; padding: 26px 30px 10px; }
  .jr-bau-status { flex: 0 0 31%; }
}
/* Phasenzeile + Szenensatz: rein per CSS aus Wurzel-Attributen (Story vor Stage) */
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="1"], .jr-bau[data-jr-bau-story="1"]:not([data-jr-bau-stage="6"])) :is(.jr-bau-phase__n[data-jb-n="1"], .jr-bau-titel__s[data-jb-n="1"]) { display: inline; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="2"], .jr-bau[data-jr-bau-story="2"]:not([data-jr-bau-stage="6"])) :is(.jr-bau-phase__n[data-jb-n="2"], .jr-bau-titel__s[data-jb-n="2"]) { display: inline; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="3"], .jr-bau[data-jr-bau-story="3"]:not([data-jr-bau-stage="6"])) :is(.jr-bau-phase__n[data-jb-n="3"], .jr-bau-titel__s[data-jb-n="3"]) { display: inline; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="4"], .jr-bau[data-jr-bau-story="4"]:not([data-jr-bau-stage="6"])) :is(.jr-bau-phase__n[data-jb-n="4"], .jr-bau-titel__s[data-jb-n="4"]) { display: inline; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"], .jr-bau[data-jr-bau-story="5"]:not([data-jr-bau-stage="6"])) :is(.jr-bau-phase__n[data-jb-n="5"], .jr-bau-titel__s[data-jb-n="5"]) { display: inline; }
[data-jr-bau-stage="6"] :is(.jr-bau-phase__n[data-jb-n="6"], .jr-bau-titel__s[data-jb-n="6"]) { display: inline; }
/* Ticks in der Story-Ebene: Fortschritt folgt der Uhr, nicht dem Server-Stage */
.jr-bau[data-jr-bau-story]:not([data-jr-bau-stage="6"]) .jr-bau-tick { background: var(--jr-line); animation: none; }
.jr-bau[data-jr-bau-story="1"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(1), .jr-bau[data-jr-bau-story="2"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(2), .jr-bau[data-jr-bau-story="3"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(3), .jr-bau[data-jr-bau-story="4"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(4), .jr-bau[data-jr-bau-story="5"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(5) { background: var(--jr-muted); animation: jb-tick 1.2s ease-in-out infinite alternate; }
.jr-bau[data-jr-bau-story="2"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(1), .jr-bau[data-jr-bau-story="3"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(-n+2), .jr-bau[data-jr-bau-story="4"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(-n+3), .jr-bau[data-jr-bau-story="5"]:not([data-jr-bau-stage="6"]) .jr-bau-tick:nth-child(-n+4) { background: var(--jr-ink); animation: none; }
/* SVG-Grundfarben (nur Reise-Tokens) */
.jr-bau svg * { transform-box: fill-box; transform-origin: center; }
.jr-bau .f-ink { fill: var(--jr-ink); }
.jr-bau .f-card { fill: var(--jr-card); }
.jr-bau .f-paper { fill: var(--jr-paper); }
.jr-bau .f-line { fill: var(--jr-line); }
.jr-bau .f-muted { fill: var(--jr-muted); }
.jr-bau .f-green { fill: var(--jr-green); }
.jr-bau .f-gsoft { fill: var(--jr-green-soft); }
.jr-bau .f-none { fill: none; }
.jr-bau .s-ink { stroke: var(--jr-ink); }
.jr-bau .s-muted { stroke: var(--jr-muted); }
.jr-bau .s-green { stroke: var(--jr-green); }
.jb-wand, .jb-dach, .jb-kran, .jb-marke, .jb-basis, .jb-mast, .jb-ausleger, .jb-zaun, .jb-fundament, .jb-umriss, .jb-fassade, .jb-fumriss, .jb-oeffnung, .jb-glas, .jb-glanz, .jb-tueren, .jb-schloss, .jb-markise, .jb-zeiten, .jb-schild, .jb-laterne, .jb-logofeld, .jb-fx-weg { pointer-events: none; }
.jb-schloss-k { transform-origin: 50% 0; }
.jr-bau-akte { display: inline; }
/* ============ Sichtbarkeit ============
   Jedes Stueck traegt data-jb-piece + data-jb-at. Grundzustand: unsichtbar. */
[data-jb-piece] { opacity: 0; }
[data-jb-piece].is-built { opacity: 1; }
/* Kinder, deren Sichtbarkeit rein aus Keyframes kommt (reduced-motion: weg) */
.jb-staub rect, .jb-tr, .jb-glanz-p, .jb-rauch rect, .jb-kf, .jb-blitz, .jb-funkel, .jb-glanz2, .jb-fein { opacity: 0; }
.jb-kuebel, .jb-rig3 { opacity: 0; }
/* --- Basis ohne Story: kumulative Endzustaende je Server-Stage --- */
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="1"] [data-jb-piece^="s1-"], .jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="2"] :is([data-jb-piece^="s1-"], [data-jb-piece^="s2-"]), .jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="3"] :is([data-jb-piece^="s1-"], [data-jb-piece^="s2-"], [data-jb-piece^="s3-"]), .jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="4"] :is([data-jb-piece^="s1-"], [data-jb-piece^="s2-"], [data-jb-piece^="s3-"], [data-jb-piece^="s4-"]), .jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"] [data-jb-piece]:not(.jb-fx-weg), [data-jr-bau-stage="6"] [data-jb-piece]:not(.jb-fx-weg) { opacity: 1; }
/* Stage 1: Kuebel giesst */
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="1"] .jb-kuebel, .jr-bau[data-jr-bau-story="1"] [data-jb-piece="s1-fundament-10"].is-built .jb-kuebel { opacity: 1; }
/* Weg-Stuecke: Endzustand von Szene 5/6 = Baustelle geraeumt */
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"] :is(.jb-kran, [data-jb-piece="s1-zaun-8"], [data-jb-piece="s1-kiste-5"], [data-jb-piece="s1-kiste-6"], [data-jb-piece="s1-werkzeug-7"]), [data-jr-bau-stage="6"] :is(.jb-kran, [data-jb-piece="s1-zaun-8"], [data-jb-piece="s1-kiste-5"], [data-jb-piece="s1-kiste-6"], [data-jb-piece="s1-werkzeug-7"]) { opacity: 0; }
/* Weg-Marken (Story): .is-built auf der Marke = Ziel faehrt ab */
.jr-bau:has([data-jb-piece="s5-kran-ab-6"].is-built) .jb-kran { opacity: 0; }
.jr-bau:has([data-jb-piece="s5-kran-ab-6"].is-built:not(.is-instant)) .jb-kran { animation: jb-abfahren calc(1.6s * var(--jb-tempo, 1)) ease-in both; }
.jr-bau:has([data-jb-piece="s5-raeumen-7"].is-built) :is([data-jb-piece="s1-zaun-8"], [data-jb-piece="s1-kiste-5"], [data-jb-piece="s1-kiste-6"], [data-jb-piece="s1-werkzeug-7"]) { opacity: 0; }
.jr-bau:has([data-jb-piece="s5-raeumen-7"].is-built:not(.is-instant)) [data-jb-piece="s1-zaun-8"] { animation: jb-weg-l calc(1.1s * var(--jb-tempo, 1)) ease-in both; }
.jr-bau:has([data-jb-piece="s5-raeumen-7"].is-built:not(.is-instant)) [data-jb-piece="s1-kiste-5"] { animation: jb-weg-r calc(1s * var(--jb-tempo, 1)) ease-in both; }
.jr-bau:has([data-jb-piece="s5-raeumen-7"].is-built:not(.is-instant)) [data-jb-piece="s1-kiste-6"] { animation: jb-weg-r calc(1s * var(--jb-tempo, 1)) .2s ease-in both; }
.jr-bau:has([data-jb-piece="s5-raeumen-7"].is-built:not(.is-instant)) [data-jb-piece="s1-werkzeug-7"] { animation: jb-weg-r calc(1s * var(--jb-tempo, 1)) .35s ease-in both; }
/* Seil-Umbau Szene 5: Kran ruestet um — Haken-Seil weg, sobald die Schild-Szene laeuft */
.jr-bau[data-jr-bau-story="5"] .jb-seil-a { opacity: 0; }
/* Schild schwebt: Seil kuerzt sich synchron, Traverse (.jb-rig3) ist Kind des Schild-Stuecks */
.jr-bau:has([data-jb-piece="s5-schild-2"].is-built:not(.is-instant)) .jb-seil-i { animation: jb-seil-sync calc(1.25s * var(--jb-tempo, 1)) cubic-bezier(.4, .1, .25, 1) both; }
.jr-bau:has([data-jb-piece="s5-schild-2"].is-built) .jb-seil-i { transform: scaleY(.54); }
[data-jb-piece="s5-schild-2"].is-built .jb-rig3 { opacity: 1; }
.jb-seil-d, .jb-seil-i { transform-origin: 50% 0; }
/* Hebezeug am Schild: erst NACH dem Festschrauben loslassen — sichtbar halten, bis die
   Abzieh-Animation laeuft (sofort weg nur bei .is-instant / reduced-motion) */
.jr-bau:has([data-jb-piece="s5-fest-3"].is-built.is-instant) :is(.jb-seil-d, .jb-rig3) { opacity: 0; }
.jr-bau:has([data-jb-piece="s5-fest-3"].is-built:not(.is-instant)) .jb-seil-i { animation: jb-abziehen calc(1.2s * var(--jb-tempo, 1)) calc(.25s * var(--jb-tempo, 1)) ease-in both; }
.jr-bau:has([data-jb-piece="s5-fest-3"].is-built:not(.is-instant)) .jb-rig3 { animation: jb-rig-weg calc(1.2s * var(--jb-tempo, 1)) calc(.25s * var(--jb-tempo, 1)) ease-in both; }
[data-jb-piece="s5-fest-3"].is-built:not(.is-instant) .jb-blitz { animation: jb-blitz .8s calc(.45s * var(--jb-tempo, 1)) ease-out both; }
/* Logo-Slot: folgt dem SVG-Stueck s5-logo-4 (euer Skript fasst NUR SVG-Stuecke an) */
.jr-bau:has([data-jb-piece="s5-logo-4"].is-built) .jr-slot-schild { opacity: 1; }
.jr-bau:has([data-jb-piece="s5-logo-4"].is-built:not(.is-instant)) .jr-slot-schild { animation: jb-logo-landet calc(1.6s * var(--jb-tempo, 1)) cubic-bezier(.35, 0, .25, 1) both; }
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"] .jr-slot-schild, [data-jr-bau-stage="6"] .jr-slot-schild { opacity: 1; }
/* Laternen-Halo: Kind von s5-licht-10 — statischer Inhalt, Puls nur als Zugabe */
.jb-halo { opacity: .75; }
/* Schild-Funkeln ab s5-glanz-5 (Funkel + Glanz sind Kinder des Stuecks) */
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"] .jb-funkel, [data-jb-piece="s5-glanz-5"].is-built .jb-funkel, [data-jr-bau-stage="6"] .jb-funkel { animation: jb-funkel 1.7s ease-in-out infinite; }
/* ============ Eintritts-Animationen (nur ueber .is-built) ============ */
[data-jb-piece="s1-kran-1"].is-built { animation: jb-rollen calc(1.7s * var(--jb-tempo, 1)) cubic-bezier(.25, .7, .3, 1) both; }
[data-jb-piece="s1-mast-2"].is-built { animation: jb-hoch calc(1.2s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 50% 100%; }
[data-jb-piece="s1-ausleger-3"].is-built { animation: jb-breit calc(1s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 0% 50%; }
[data-jb-piece="s1-seil-4"].is-built { animation: jb-ziegel calc(.9s * var(--jb-tempo, 1)) cubic-bezier(.35, 0, .25, 1) both; }
[data-jb-piece="s1-kiste-5"].is-built { animation: jb-fallen calc(1.3s * var(--jb-tempo, 1)) cubic-bezier(.3, 0, .3, 1) both; }
[data-jb-piece="s1-kiste-6"].is-built { animation: jb-fallen calc(1.3s * var(--jb-tempo, 1)) cubic-bezier(.3, 0, .3, 1) both; }
[data-jb-piece="s1-werkzeug-7"].is-built .jb-t { animation: jb-rein calc(.9s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; }
[data-jb-piece="s1-zaun-8"].is-built .jb-t { animation: jb-ein calc(.6s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s1-zaun-8"].is-built .jb-kegel { animation: jb-pop-s calc(.5s * var(--jb-tempo, 1)) calc(.5s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s1-graben-9"].is-built .jb-riss { animation: jb-zeichnen calc(1.2s * var(--jb-tempo, 1)) cubic-bezier(.4, 0, .3, 1) both; }
[data-jb-piece="s1-graben-9"].is-built .jb-t { animation: jb-pop-s calc(.4s * var(--jb-tempo, 1)) calc(1s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s1-fundament-10"].is-built .jb-t { animation: jb-giessen calc(1.2s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 50% 100%; }
[data-jb-piece="s1-fundament-11"].is-built .jb-t { animation: jb-giessen calc(1.2s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 50% 100%; }
[data-jb-piece="s1-fundament-11"].is-built .jb-t2 { animation: jb-ein calc(.7s * var(--jb-tempo, 1)) calc(.9s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s2-kreide-1"].is-built .jb-riss { animation: jb-zeichnen calc(1.6s * var(--jb-tempo, 1)) cubic-bezier(.4, 0, .3, 1) both; }
[data-jb-piece="s2-pfeiler-2"].is-built .jb-t { animation: jb-hoch calc(1s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 50% 100%; }
:is([data-jb-piece="s2-reihe-3"], [data-jb-piece="s2-reihe-4"], [data-jb-piece="s2-reihe-5"], [data-jb-piece="s2-reihe-6"]).is-built .jb-stein { animation: jb-stein calc(.55s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .3, 1.2) both; }
[data-jb-piece="s2-fassade-7"].is-built { animation: jb-ein calc(.8s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s2-vorzeichnen-8"].is-built .jb-riss { animation: jb-zeichnen calc(1s * var(--jb-tempo, 1)) cubic-bezier(.4, 0, .3, 1) both; }
[data-jb-piece="s2-oeffnung-9"].is-built .jb-t { animation: jb-ein calc(.55s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s2-sturz-10"].is-built { animation: jb-pop-s calc(.5s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s3-riss-1"].is-built .jb-riss { animation: jb-zeichnen calc(1.4s * var(--jb-tempo, 1)) cubic-bezier(.4, 0, .3, 1) both; }
[data-jb-piece="s3-balken-2"].is-built { animation: jb-balken calc(1.6s * var(--jb-tempo, 1)) cubic-bezier(.3, 0, .25, 1) both; }
[data-jb-piece="s3-balken-3"].is-built { animation: jb-balken calc(1.6s * var(--jb-tempo, 1)) cubic-bezier(.3, 0, .25, 1) both; }
[data-jb-piece="s3-first-4"].is-built { animation: jb-balken calc(1.4s * var(--jb-tempo, 1)) cubic-bezier(.3, 0, .25, 1) both; }
[data-jb-piece="s3-ziegel-l-5"].is-built .jb-t { animation: jb-ziegel calc(.8s * var(--jb-tempo, 1)) cubic-bezier(.25, .6, .3, 1) both; }
[data-jb-piece="s3-ziegel-r-6"].is-built .jb-t { animation: jb-ziegel calc(.8s * var(--jb-tempo, 1)) cubic-bezier(.25, .6, .3, 1) both; }
[data-jb-piece="s3-schornstein-7"].is-built { animation: jb-senken-fern calc(1.5s * var(--jb-tempo, 1)) cubic-bezier(.35, 0, .25, 1) both; }
[data-jb-piece="s3-gaube-8"].is-built { animation: jb-pop-s calc(.55s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s3-traufe-9"].is-built .jb-t { animation: jb-ein calc(.6s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-rahmen-l-1"].is-built .jb-t { animation: jb-ein calc(.5s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-rahmen-r-2"].is-built .jb-t { animation: jb-ein calc(.5s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-glas-l-3"].is-built .jb-gl { animation: jb-ein calc(.6s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-glas-r-4"].is-built .jb-gl { animation: jb-ein calc(.6s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-tuerrahmen-5"].is-built .jb-t { animation: jb-ein calc(.55s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-tueren-6"].is-built .jb-t { animation: jb-ein calc(.7s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s4-schloss-7"].is-built { animation: jb-pop-s calc(.5s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both, jb-klick calc(.5s * var(--jb-tempo, 1)) calc(.75s * var(--jb-tempo, 1)) ease-in-out 1; }
[data-jb-piece="s4-markise-l-8"].is-built { animation: jb-falten calc(.6s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .3, 1.2) both; transform-origin: 50% 0; }
[data-jb-piece="s4-markise-r-9"].is-built { animation: jb-falten calc(.6s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .3, 1.2) both; transform-origin: 50% 0; }
[data-jb-piece="s4-zeiten-10"].is-built { animation: jb-pop-s calc(.5s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s5-seil-1"].is-built { animation: jb-seil-lang calc(1.1s * var(--jb-tempo, 1)) cubic-bezier(.35, 0, .25, 1) both; transform-origin: 50% 0; }
[data-jb-piece="s5-schild-2"].is-built { animation: jb-heben calc(1.25s * var(--jb-tempo, 1)) cubic-bezier(.4, .1, .25, 1) both; }
[data-jb-piece="s5-fest-3"].is-built .jb-t { animation: jb-pop-s calc(.4s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s5-logo-4"].is-built { animation: jb-ein calc(.7s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s5-laterne-l-8"].is-built .jb-t { animation: jb-hoch calc(.9s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 50% 100%; }
[data-jb-piece="s5-laterne-r-9"].is-built .jb-t { animation: jb-hoch calc(.9s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; transform-origin: 50% 100%; }
[data-jb-piece="s5-licht-10"].is-built .jb-t { animation: jb-ein calc(.6s * var(--jb-tempo, 1)) both; }
[data-jb-piece="s5-gruen-11"].is-built .jb-t { animation: jb-pop-s calc(.5s * var(--jb-tempo, 1)) cubic-bezier(.2, .8, .3, 1.25) both; }
[data-jb-piece="s5-tisch-12"].is-built .jb-t { animation: jb-rein calc(.9s * var(--jb-tempo, 1)) cubic-bezier(.2, .7, .25, 1) both; }
/* Sofort-Zustand: Reload mitten in der Story — Endlage ohne Eintritt */
[data-jb-piece].is-instant, [data-jb-piece].is-instant .jb-t, [data-jb-piece].is-instant .jb-t2, [data-jb-piece].is-instant .jb-gl, [data-jb-piece].is-instant .jb-stein, [data-jb-piece].is-instant .jb-riss, [data-jb-piece].is-instant .jb-kegel { animation: none !important; }
/* ============ Ambiente-Loops (folgen Story-Nr., sonst Stage-Nr.) ============ */
:is(.jr-bau:not([data-jr-bau-story]):is([data-jr-bau-stage="1"], [data-jr-bau-stage="2"], [data-jr-bau-stage="3"], [data-jr-bau-stage="4"], [data-jr-bau-stage="5"]), .jr-bau[data-jr-bau-story]) .jb-wimpel { animation: jb-wehen 2.4s ease-in-out infinite alternate; transform-origin: 0% 50%; }
:is(.jr-bau:not([data-jr-bau-story]):is([data-jr-bau-stage="1"], [data-jr-bau-stage="2"], [data-jr-bau-stage="3"]), .jr-bau:is([data-jr-bau-story="1"], [data-jr-bau-story="2"], [data-jr-bau-story="3"])) .jb-staub rect { animation: jb-staub 2.1s ease-in-out infinite; }
:is(.jr-bau:not([data-jr-bau-story]):is([data-jr-bau-stage="1"], [data-jr-bau-stage="2"], [data-jr-bau-stage="3"], [data-jr-bau-stage="4"]), .jr-bau:is([data-jr-bau-story="1"], [data-jr-bau-story="2"], [data-jr-bau-story="3"], [data-jr-bau-story="4"])) .jb-seil-a { animation: jb-pendel 3.2s ease-in-out infinite alternate; transform-origin: 50% 0; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="1"], .jr-bau[data-jr-bau-story="1"]) .jb-kuebel { animation: jb-kippen 2.6s .6s ease-in-out infinite; transform-origin: 50% 0; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="1"], .jr-bau[data-jr-bau-story="1"]) .jb-tr { animation: jb-tropfen 1.15s linear infinite; }
:is(.jr-bau:not([data-jr-bau-story]):is([data-jr-bau-stage="4"], [data-jr-bau-stage="5"]), .jr-bau:is([data-jr-bau-story="4"], [data-jr-bau-story="5"]), [data-jr-bau-stage="6"]) .jb-glanz-p { animation: jb-schimmer 2.4s ease-in-out infinite alternate; }
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"] .jb-glanz2, [data-jb-piece="s5-glanz-5"].is-built .jb-glanz2, [data-jr-bau-stage="6"] .jb-glanz2 { animation: jb-gleiten 4.5s ease-in-out 1.2s infinite; }
.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"] .jb-halo, [data-jb-piece="s5-licht-10"].is-built .jb-halo, [data-jr-bau-stage="6"] .jb-halo { animation: jb-halo 2.2s ease-in-out infinite; }
:is(.jr-bau:not([data-jr-bau-story])[data-jr-bau-stage="5"], .jr-bau:has([data-jb-piece="s5-letzte-13"].is-built), [data-jr-bau-wait="1"]) .jb-fein { animation: jb-funkel 2.3s ease-in-out infinite; }
.jb-fein2 { animation-delay: 1.15s; }
/* ---- Phase 6 · Der Bau steht (unveraendert zu Lieferung 1) ---- */
[data-jr-bau-stage="6"] .jb-li { animation: jb-ein .5s both; }
[data-jr-bau-stage="6"] .jb-girlande { animation: jb-ein .5s .1s both; }
[data-jr-bau-stage="6"] .jb-bulb-a { animation: jb-blink 1.6s ease-in-out infinite alternate; }
[data-jr-bau-stage="6"] .jb-bulb-b { animation: jb-blink 1.6s .8s ease-in-out infinite alternate; }
[data-jr-bau-stage="6"] .jb-tuer-l { transform-origin: 0% 50%; transform: scaleX(.13); animation: jb-tuer .9s 1.2s cubic-bezier(.4, 0, .2, 1) both; }
[data-jr-bau-stage="6"] .jb-tuer-r { transform-origin: 100% 50%; transform: scaleX(.13); animation: jb-tuer .9s 1.2s cubic-bezier(.4, 0, .2, 1) both; }
[data-jr-bau-stage="6"] .jb-rauch rect { animation: jb-rauch 2.6s ease-out infinite; }
[data-jr-bau-stage="6"] .jb-kf { animation: jb-fall var(--d, 5s) linear var(--dl, 0s) infinite; }
[data-jr-bau-stage="6"] .jb-halo { fill: var(--jr-green-soft); }
.jb-girlande, .jb-lichter, .jb-rauch, .jb-konfetti { opacity: 0; }
[data-jr-bau-stage="6"] :is(.jb-girlande, .jb-lichter, .jb-rauch, .jb-konfetti) { opacity: 1; }
/* ⭐⭐ N12 · 27.08.2026 — DAS LICHT SCHEINT DURCH DIE FENSTER, ES LÖSCHT SIE NICHT.
   🔬 GEMESSEN AN DER GEOMETRIE DER SZENE: `.jb-li` zeichnet volldeckende
   Rechtecke exakt über die Scheiben (154–202 / 192–230, 348–396 und die Türfläche
   217–333) und steht im Dokument NACH ihnen. Mit `--jr-green-soft` (#e7f8ef,
   fast weiß) verschwanden Sprossen, Rahmenlinien und Türblätter unter einer
   blassen Fläche — das Gebäude wirkte in Szene 6 leerer als in Szene 5.
   ⭐ DIE REPARATUR IST FARBE UND DECKKRAFT, NICHT GEOMETRIE: die Szene selbst ist
   die Lieferung und wird Byte für Byte gegen sie geprüft (BAU-2), also darf das
   SVG nicht angefasst werden. Warmes Licht bei halber Deckkraft liegt ÜBER den
   Scheiben und lässt sie durch — und warm ist auch das, was ein beleuchtetes
   Lokal von innen abgibt.
   ⛔ NUR `.jb-li`: die Girlande und der Halo behalten ihr Grün, weil sie die
   Aussage der Szene tragen. */
.jr-bau .jb-li.f-gsoft { fill: var(--jr-amber-soft); }
.jb-li { opacity: .5; }
/* ⚖️ EIGENTÜMER, 27.08.2026 — die zwei grünen Dreiecke vor der Tür gehen.
   ⛔ DAS STÜCK BLEIBT, NUR SEINE FLÄCHE GEHT. `data-jb-piece="s5-gruen-11"` ist
   ein Takt der Erzählung: seine Zeit (`data-jb-at="91.4"`) hält die
   Dichte-Regel, sein Name trägt den Textschlüssel `bau_a_s5_gruen_11`, und das
   Löschen des Elements hieße das SVG anzufassen, das gegen die Lieferung geprüft
   wird. Genau so sind `s5-kran-ab-6` und `s5-raeumen-7` seit jeher leere Marken.
   ⛔ `display`, nicht `opacity`: die Sichtbarkeitsregeln dieser Szene setzen
   `opacity: 1` auf jedes gebaute Stück und hätten es zurückgeholt. */
[data-jb-piece="s5-gruen-11"] { display: none; }
/* ---- HTML-Overlay: die zwei Slots ---- */
.jr-bau-overlay { position: absolute; inset: 0; pointer-events: none; }
.jr-slot-schild { position: absolute; inset-block-start: 43.33%; inset-inline-start: 31.25%; width: 52.09%; height: 21.11%; display: flex; align-items: center; justify-content: center; opacity: 0; }
.jr-slot-logo { height: 92%; aspect-ratio: 1; object-fit: contain; display: block; }
.jr-slot-name { font-weight: 800; font-size: 7.2cqi; letter-spacing: .1em; text-transform: uppercase; color: var(--jr-ink); white-space: nowrap; text-align: center; line-height: 1.05; }
.jr-slot-name--long { font-size: 5.4cqi; letter-spacing: .08em; }
.jr-slot-name--xlong { font-size: 4.1cqi; letter-spacing: .06em; white-space: normal; max-height: 100%; overflow: hidden; }
.jr-slot-name--xxlong { font-size: 3.3cqi; letter-spacing: .04em; white-space: normal; max-height: 100%; overflow: hidden; }
.jr-slot-tuer { position: absolute; inset-inline-start: 44.79%; width: 25%; top: 66.11%; height: 17.22%; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.jr-slot-eintreten { pointer-events: auto; display: none; flex: none; align-items: center; justify-content: center; white-space: nowrap; min-width: 44px; min-height: 44px; max-width: 100%; max-height: 100%; padding: .45em .7em; background: var(--jr-accent); color: #fff; border: none; border-radius: 0; font: inherit; font-weight: 800; font-size: clamp(12px, 3.2cqi, 17px); letter-spacing: .05em; cursor: pointer; }
.jr-slot-eintreten:hover { background: var(--jr-accent-hover); }
.jr-slot-eintreten:focus-visible { outline: 2px solid var(--jr-ink); outline-offset: 2px; }
[data-jr-bau-stage="6"] .jr-slot-eintreten { display: inline-flex; animation: jb-pop .55s 2.2s cubic-bezier(.2, .8, .3, 1.2) both, jb-puls 2.2s 3.4s infinite; }
.jr-bau-hand { position: absolute; width: clamp(20px, 6.4cqi, 32px); aspect-ratio: 1; inset-inline-start: 58%; top: 52%; color: var(--jr-ink); pointer-events: none; display: none; opacity: 0; filter: drop-shadow(0 1px 0 rgba(19, 25, 54, .15)); }
[data-jr-bau-stage="6"] .jr-bau-hand { display: block; animation: jb-hand 3.4s 2.6s ease-in-out both; }
/* ---- RTL: EINE Regel spiegelt die Buehne; Overlays logisch gesetzt ---- */
body.jr-page[dir="rtl"] .jr-bau-buehne > svg { transform: scaleX(-1); }
/* ---- [hidden] gewinnt immer (Falle Lieferung 1) ---- */
.jr-bau [hidden] { display: none !important; }
/* ---- Reduced Motion: keine Bewegung; .is-built = Endlage sofort; Deko weg ---- */
@media (prefers-reduced-motion: reduce) {
  .jr-bau *, .jr-bau *::before, .jr-bau *::after { animation: none !important; transition: none !important; }
  .jr-bau:has([data-jb-piece="s5-fest-3"].is-built) :is(.jb-seil-d, .jb-rig3) { opacity: 0; }
}
/* ---- what this file adds to the delivery: <p> resets, the chip's tick, the two screens ---- */
.jr-bau-phase, .jr-bau-titel, .jr-bau-sub, .jr-bau-akt { margin: 0; font-family: inherit; }
.jr-bau-phase { line-height: 1.3; }
.jr-bau-phase__n { font-variant-numeric: tabular-nums; }
.jr-bau-titel { color: var(--jr-ink); }
.jr-bau-sub { font-weight: 400; line-height: 1.5; }
.jr-bau-fertig { font-family: inherit; line-height: 1.3; }
.jr-bau-fertig__tick { flex: 0 0 auto; }
/* the building screen: the "you do not have to wait" card follows the scene */
.jr-bau + .jr-card { margin-block-start: 12px; }
/* the success window: the scene sits on the green ground, not on a white card */
.jr-done .jr-bau { background: transparent; }
.jr-done .jr-bau-innen { padding: 4px 0 0; }
/* 🔬 MEASURED ON THE FIRST RUN OF THE PROBE (25.08.2026): on a 390 px phone the
   picture stood 295 px wide inside the scene's 18 px padding and the owner's logo
   came out at 43 px — ONE pixel under the 44 the brief promised (the spec board
   had measured 46 on a bare 390 px card, without this card's own edges). The
   picture may use the card's width on a phone; the words keep their indent, the
   overlays are percentages of the picture and move with it. 319 px → 46 px. */
@container (max-width: 639px) {
  .jr-bau-buehne { margin-inline: -12px; }
}
/* ---- Keyframes ---- */
@keyframes jb-ein { from { opacity: 0; } }
@keyframes jb-pop { from { opacity: 0; transform: scale(.6); } }
@keyframes jb-pop-s { from { opacity: 0; transform: scale(.4); } }
@keyframes jb-stein { from { opacity: 0; transform: translateY(14px); } }
@keyframes jb-hoch { from { opacity: 0; transform: scaleY(.15); } }
@keyframes jb-breit { from { opacity: 0; transform: scaleX(.05); } }
@keyframes jb-rein { from { opacity: 0; transform: translateX(74px); } }
@keyframes jb-rollen { 0% { opacity: 0; transform: translateX(-190px); } 12% { opacity: 1; } 78% { transform: translateX(5px); } 100% { transform: none; } }
@keyframes jb-fallen { 0% { opacity: 0; transform: translateY(-215px); } 18% { opacity: 1; } 62% { transform: translateY(0); } 76% { transform: translateY(-6px); } 100% { transform: none; } }
@keyframes jb-balken { 0% { opacity: 0; transform: translateY(-130px) rotate(1.6deg); } 22% { opacity: 1; } 82% { transform: translateY(2px) rotate(0deg); } 100% { transform: none; } }
@keyframes jb-ziegel { from { opacity: 0; transform: translateY(-14px); } }
@keyframes jb-senken-fern { 0% { opacity: 0; transform: translateY(-120px); } 25% { opacity: 1; } 100% { transform: none; } }
@keyframes jb-wehen { from { transform: rotate(4deg); } to { transform: rotate(-5deg); } }
@keyframes jb-staub { 0%, 100% { opacity: 0; transform: translateY(0) scale(.5); } 45% { opacity: .85; transform: translateY(-7px) scale(1.15); } }
@keyframes jb-pendel { from { transform: rotate(2.2deg); } to { transform: rotate(-2.2deg); } }
@keyframes jb-giessen { from { transform: scaleY(0); } }
@keyframes jb-zeichnen { from { stroke-dashoffset: 100; } }
@keyframes jb-kippen { 0%, 15% { transform: rotate(0); } 45%, 70% { transform: rotate(-16deg); } 95%, 100% { transform: rotate(0); } }
@keyframes jb-tropfen { 0% { opacity: 0; transform: translateY(0); } 12% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; transform: translateY(148px); } }
@keyframes jb-weg-r { to { opacity: 0; transform: translateX(70px); } }
@keyframes jb-weg-l { to { opacity: 0; transform: translateX(-52px); } }
@keyframes jb-abfahren { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-210px); } }
@keyframes jb-seil-lang { from { transform: scaleY(.05); } }
@keyframes jb-seil-sync { 0%, 16% { transform: scaleY(1); } 100% { transform: scaleY(.54); } }
@keyframes jb-heben { 0% { opacity: 0; transform: translateY(78px); } 8% { opacity: 1; transform: translateY(78px); } 16% { transform: translateY(78px); } 62% { transform: translateY(26px) rotate(.7deg); } 86% { transform: translateY(3px) rotate(-.4deg); } 100% { transform: none; } }
@keyframes jb-abziehen { to { opacity: 0; transform: scaleY(.05); } }
@keyframes jb-rig-weg { to { opacity: 0; transform: translateY(-48px); } }
@keyframes jb-logo-landet { 0% { opacity: 0; transform: translateY(-150%); } 14% { opacity: 1; } 58% { transform: translateY(0); } 74% { transform: translateY(-3%); } 100% { transform: none; } }
@keyframes jb-halo { 0%, 100% { opacity: .35; } 50% { opacity: .95; } }
@keyframes jb-tuer { from { transform: scaleX(1); } }
@keyframes jb-rauch { 0% { opacity: 0; transform: translateY(6px) scale(.6); } 30% { opacity: .7; } 100% { opacity: 0; transform: translateY(-16px) scale(1.15); } }
@keyframes jb-blitz { 0% { opacity: 0; transform: scale(.2) rotate(0deg); } 35% { opacity: 1; transform: scale(1.2) rotate(20deg); } 100% { opacity: 0; transform: scale(.5) rotate(40deg); } }
@keyframes jb-funkel { 0%, 100% { opacity: 0; transform: scale(.4); } 50% { opacity: 1; transform: scale(1); } }
@keyframes jb-falten { from { opacity: 0; transform: scaleY(.1); } }
@keyframes jb-klick { 0% { transform: rotate(0); } 30% { transform: rotate(-14deg); } 60% { transform: rotate(9deg); } 100% { transform: rotate(0); } }
@keyframes jb-schimmer { from { opacity: .05; } to { opacity: .8; } }
@keyframes jb-blink { from { opacity: .35; } to { opacity: 1; } }
@keyframes jb-fall { from { opacity: 1; transform: translateY(-18px) rotate(0deg); } to { opacity: 1; transform: translateY(318px) rotate(210deg); } }
@keyframes jb-gleiten { 0% { opacity: 0; transform: translateX(0) skewX(-16deg); } 10% { opacity: .9; } 45% { opacity: .9; } 55%, 100% { opacity: 0; transform: translateX(290px) skewX(-16deg); } }
@keyframes jb-tick { from { opacity: .35; } to { opacity: 1; } }
@keyframes jb-bullet { from { opacity: .3; } to { opacity: 1; } }
@keyframes jb-satz { from { opacity: 0; transform: translateY(3px); } }
@keyframes jb-hand { 0% { opacity: 0; transform: translate(4px, 8px); } 12% { opacity: 1; transform: translate(0, 0); } 26% { transform: translate(-3px, -5px) scale(.93); } 38% { transform: translate(0, 0) scale(1); } 52% { transform: translate(-3px, -5px) scale(.93); } 64% { transform: translate(0, 0) scale(1); } 84% { opacity: 1; } 100% { opacity: 0; transform: translate(2px, 5px); } }
@keyframes jb-puls { 0% { box-shadow: 0 0 0 0 rgba(18, 183, 106, .45); } 70%, 100% { box-shadow: 0 0 0 14px transparent; } }

/* The clock, big — the delivery's own 30 px, beside the headline.
   ⭐⭐ N8 — IT COUNTS DOWN NOW (owner, 23.08.2026), and the class says so: it was
   `.jr-elapsed` while the number was "läuft seit", and a name that means the
   opposite of what the element holds is the same hazard as a comment that does
   — the reason D7 renamed `.jr-live` to `.jr-clip`.
   ⛔ It is still a SERVER measurement drawn once per render; `jr-countdown.js`
   only subtracts seconds it has itself watched pass. The digits stay 0–9 in
   every language because the value is an LTR token in its own element. */
.jr-prov-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.jr-prov-head > :first-child { min-width: 0; }
.jr-prov-head .jr-h1 { margin: 0; }
.jr-countdown { flex: 0 0 auto; text-align: end; }
.jr-countdown__k { display: block; font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.3; color: var(--jr-muted); }
.jr-countdown__v { display: block; font-family: inherit; font-weight: 700; font-size: 30px; line-height: 1; }

/* ⛔⭐ THE LIVE REGION IS EMPTY IN THE MARKUP AND INVISIBLE ON THE SCREEN.
   `jr-live.js` copies the CURRENT PHASE'S OWN SENTENCE into it — a sentence the
   SERVER rendered, in the reader's language — and only when the phase really
   changed between two renders. Nothing here is ever seen; it exists so a screen
   reader is TOLD about a change the eye can simply watch happen.
   🔴 AND THE `hidden` TRAP DOES NOT APPLY, because this must not be hidden at
   all: `[hidden]` and `display: none` both take an element out of the
   accessibility tree, and a live region nothing can read announces nothing. The
   clipped single pixel is the one geometry that hides and still speaks.

   🔴🔴 D6 FOUND THAT THIS RULE HAD BEEN WRITTEN TWICE, AND D7 DELETED IT.
   D5 gave the clipped geometry the class name `.jr-live` — which P3.8 had
   ALREADY used, 700 lines up, for the VISIBLE "we are drawing your logo" line (a
   flex row with a pulsing dot beside a sentence). Two rules, one name, equal
   specificity, the clipping one later in the file ⇒ the logo station's waiting
   line was invisible for a day. Nothing caught it, and the reason is worth
   keeping: the browser gate's clipped-text sweep looks at
   `h1, h2, p, label, span, button, a, legend, summary`, and the crushed element
   was a `div`; the `span` inside it measures its own full width and overflows its
   PARENT, which is not what that sweep asks about.

   ⇒ D6 repaired it by selecting on the CONTRACT (`.jr-live[data-jr-live]`) and
   recorded the rest for D7, because the geometry already existed under its own
   name: **`.jr-clip`** (from W1, for the logo station's file input) — the same
   ten declarations, and a name that means only this. D7 moved the three live
   regions onto it and deleted the duplicate, so `.jr-live` has exactly one
   meaning in this file again. There is nothing left here to override, which is
   why the `display` restatement went with it.

   ⛔ THE TWO THINGS THAT MUST STAY TRUE OF `.jr-clip` ARE NOW ONE RULE: it hides
   without leaving the accessibility tree (never `[hidden]`, never
   `display: none`), and it takes a `<p>`'s user-agent margins away. Both are
   asserted, and the assertions moved with the class. */

/* --- what the width is FOR, on these screens -----------------------------
   ⛔ THREE SCREENS, NOT FOUR. `dpa` is deliberately NOT widened: it is one legal
   sentence, one card and one checkbox, and there is no second column for any of
   them. A 1120-px shell around that is exactly the "very wide single column"
   this file's own `--wide` note calls worse than a centred phone column, so the
   station stays where it reads best. The width is granted where a layout uses
   it, and nowhere else.

   ⛔ AND EACH RULE ASKS ABOUT CONTENT, because both lists can legitimately be
   SHORT: `settled` collapses the verdict to one row, and a provisioning that has
   not begun has no card to put beside anything. Two columns around one row is
   the defect, not the layout. `review` needs no rule here at all — its grid is
   `auto-fit` and answers the question by itself.

   🔴 G1 · `dpa` NOW TAKES THE SHEET, AND STILL HAS NO SECOND COLUMN — the two
   are different questions (see the `--wide` note). Measured, the delivery draws
   this board at 1072 px like every other, and the widest line it paints there is
   its own: 163 ch / 978 px, against 82 ch on ours. Nothing below changes: no
   rule here ever named `dpa`, and none acquires one. */
@media (min-width: 834px) {
  /* Four criteria or more: two columns of rows. The criteria are independent of
     one another and read as a set rather than as a sequence, which is what makes
     splitting them honest.
     ⛔ `:has(> :nth-child(4))` — with `settled` there is exactly ONE row and the
     list stays a list. */
  .jr-shell--wide .jr-checks--verdict:has(> :nth-child(4)) {
    display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  }
  .jr-shell--wide .jr-checks--verdict:has(> :nth-child(4)) > .jr-check-row:nth-child(2) { border-block-start: none; }
  .jr-shell--wide .jr-checks--verdict:has(> :nth-child(4)) > .jr-check-row:nth-child(even) {
    border-inline-start: 1px solid var(--jr-line-soft);
  }
}

/* --- D5 · three tap targets that were text ---------------------------------
   ⛔⭐ MEASURED, NOT PREFERRED. Every interactive thing on these screens was put
   under the 44-px floor the browser gate applies, and three of them failed: the
   review's "Ändern" links (17 px of text), the agreement link on the acceptance
   (20 px of underlined text), and the consent checkbox's own label (a bare flex
   row with no padding at all). All three are what an owner is meant to TAP, on
   a phone, and two of them are the only way back and the only way to read a
   contract before agreeing to it. */

/* ⭐ THE HIT AREA GROWS AND THE INK DOES NOT. Padding plus the same negative
   margin gives the link a 45-px box without moving one pixel of the layout it
   sits in — the head row is baseline-aligned and would have shifted under real
   padding. The three tiles' headings are text, so the enlarged boxes overlap
   nothing that can be pressed. */
.jr-edit { padding-block: 14px; margin-block: -14px; }

/* The agreement, as the delivery draws it: a full-width row with a chevron, not
   a sentence with an underline in it. It is the one thing on that screen an
   owner is asked to read BEFORE agreeing, and it was the smallest target on it. */
.jr-doclink {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  /* ⚖️ OWNER 23.08.2026 · A MARGIN UNDERNEATH TOO. It had `12px 0 0`, so on
     `dpa` the "read the agreement" row sat flush against the card that follows
     it and the two read as one block — on the screen whose whole point is that
     the reading happens BEFORE the consent below. */
  min-height: 52px; margin: 12px 0 16px; padding: 12px 14px;
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius); background: var(--jr-card);
  font-family: inherit; font-weight: 600; font-size: 14.5px; line-height: 1.35;
  color: var(--jr-ink); text-decoration: none;
}
.jr-doclink:hover { border-color: var(--jr-line-strong); }
.jr-doclink:focus-visible { outline: 3px solid var(--jr-accent); outline-offset: 2px; }
/* ⚖️ THE CHEVRON MIRRORS IN ARABIC and is drawn rather than written, so no glyph
   enters the accessibility tree beside a link that already has words. */
.jr-doclink::after {
  content: ""; flex: 0 0 auto; width: 9px; height: 9px;
  border-block-start: 2.2px solid var(--jr-muted); border-inline-end: 2.2px solid var(--jr-muted);
  transform: rotate(45deg);
}
body.jr-page[dir="rtl"] .jr-doclink::after { transform: rotate(-135deg); }

/* ── N18 (29.08.2026) · THE TWO READING DOORS ON `dpa` ───────────────────────
   ⭐ Two doors stand on the consent screen: the plain-language EXPLANATION
   (`d_more`) beside the lede, and the AGREEMENT itself (`d_read`) beside the
   tick. Neither is ever the primary — `.jr-cta` keeps the accent and keeps the
   footer; these never leave the body of the sheet.

   ── 🔴🔴 K-2 · 30.08.2026 · OWNER — AND NEITHER IS A CONTROL ANY MORE ─────────
   «هيك على سطر واحد بنفس الخط و الحجم و كل شيء بس … تكون بلون خط ازرق و تكون
    الرابط … مو متل هلأ هيك مفصولين!»

   ⛔ `.jr-morebtn` AND `.jr-lederow` ARE DELETED, NOT DISABLED. N18 drew the
   explanation as a filled blue button in a flex row beside the paragraph. A
   button is a thing to DO, and it sat some distance to the right of the sentence
   it belonged to — so a screen whose whole point is one irreversible press
   carried a second coloured control that read as a competing act. Both classes
   had exactly one caller (`screen_dpa.php`) and it no longer names them; a rule
   nobody renders is the `p_elapsed` defect in CSS.
   ⇒ `.jr-textlink` replaces both: the last words of the sentence, in the
   sentence's own font — `font: inherit` is the whole point, so it is right in the
   lede's 400/14.5 muted paragraph AND in the tick's 500/14.5 row without one
   value being written twice. */
.jr-textlink {
  /* ⛔ `font: inherit` AND NOTHING ELSE ABOUT TYPE. The owner asked for "same
     font, same size, everything" — the only two departures are the colour and
     the underline that make it readable as a link at all. A `font-weight` here
     would be a third. */
  font: inherit;
  /* ── 🔴 K-2b · 30.08.2026 · OWNER — «بدون خطوط تحت نصوص الروابط» ────────────
     ⛔ NO UNDERLINE AT REST. The colour carries the link on its own.
     🔬 AND THE MEASUREMENT THAT GOES WITH IT, recorded because it is a real
     cost and not a style opinion: WCAG 1.4.1 asks for 3:1 between a link and the
     text around it when colour is the ONLY cue. Measured on our own tokens —
     blue #1b5fd9 against the consent row's ink #131936 is 3.02:1 (it passes),
     against the lede's muted #454d6b it is 1.46:1 (it does not). A reader who
     cannot separate blue from grey will not see the lede's door. The owner has
     ruled; this is where the ruling is written down.
     ⚖️ SO THE NON-COLOUR CUE MOVES TO HOVER AND FOCUS, where it costs the
     resting screen nothing: a mouse or a keyboard still announces the link. */
  color: var(--jr-blue); text-decoration: none; text-underline-offset: 3px;
  /* ⚖️ D5's 44-px floor, bought the way `.jr-edit` buys it: padding grows the
     HIT AREA, the matching negative margin gives the growth back to the layout.
     Inline (inside `.jr-lede`) vertical margins are ignored and vertical padding
     never touches the line box, so the sentence does not move; as a flex item
     (inside `.jr-consent--card`) the margin cancels the padding, so the row does
     not grow. One rule, correct in both places.
     🔬 15 px AND NOT `.jr-edit`'s 14: an INLINE box is as tall as the font's own
     metrics (16 px here), not as tall as its line-height, so 14 measured 40 px in
     four of the five languages. Measured on the live screen at three widths in
     all five — 46 px inline, 50 px in the row. Never guessed. */
  padding-block: 15px; margin-block: -15px;
}
.jr-textlink:hover { color: var(--jr-blue-hover); text-decoration: underline; }
.jr-textlink:focus-visible {
  outline: 3px solid var(--jr-accent); outline-offset: 2px; border-radius: 6px;
  text-decoration: underline;
}

/* ⚖️ 44 px WITHOUT A BORDER for the standalone case too. `.jr-doclink` bought its
   tap target with a bordered row and the owner struck the box («بلا ما تكون هيك
   بحاوية مع سهم») — so the height comes from `padding-block` and `min-height`.
   ⛔ `.jr-inlink` SURVIVES FOR ACT 2 ALONE, where the agreement link stands on a
   line of its own under the record and has no sentence to sit inside. */
.jr-inlink {
  display: inline-flex; align-items: center; min-height: 44px;
  padding-block: 10px; padding-inline: 2px; margin-inline: -2px;
  font-family: inherit; font-weight: 700; font-size: 14.5px; line-height: 1.35;
  color: var(--jr-blue); text-decoration: underline; text-underline-offset: 3px;
}
.jr-inlink:hover { color: var(--jr-blue-hover); }
.jr-inlink:focus-visible { outline: 3px solid var(--jr-accent); outline-offset: 2px; border-radius: 6px; }
/* Act 2 has no consent sentence to stand beside, so there the link is its own
   line and needs the block margins `.jr-consent`'s gap supplies in act 1. */
.jr-inlink--own { display: flex; margin: 4px 0 14px; }

/* The consent row: the tick and the agreement link side by side, wrapping to two
   lines when the sentence no longer leaves room for the link.
   ⛔ `align-items: center` and NOT `stretch` — a stretched link would grow to the
   row's full height and its underline would sit nowhere near the sentence. */
.jr-consent { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; }
.jr-consent > .jr-check--card { flex: 1 1 260px; }

/* ── 🔴🔴 K-2 · 30.08.2026 · OWNER — THE BOX MOVES FROM THE LABEL TO THE ROW ───
   «Ich stimme … zu. Vereinbarung lesen — مو متل هلأ هيك مفصولين!»
   The frame belonged to the `<label>`, so the link could only ever stand OUTSIDE
   it, pushed to the far right end of the row. The frame is the same frame; it
   simply wraps both halves now, and the link sits directly after the sentence.

   ⛔ AND THE LABEL KEEPS ITS CLASSES. `.jr-check--card` is what makes the tick
   accent-red when checked (`.jr-check` alone paints it ink) and 22 px wide, and
   the ALLERGEN station renders the very same label — so the class is stripped of
   its box HERE, in this row's scope, and nowhere else. Flattened rather than
   swapped: two classes for one control would have been the drift.
   ⛔ THE `<a>` IS STILL A SIBLING of the `<label>`, which is the rule this whole
   row exists for — a link inside a `<label for>` would tick the Art.-28 box. */
.jr-consent--card {
  align-items: center; gap: 3px 8px;
  min-height: 52px; margin-top: 12px; padding: 13px 14px;
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius); background: var(--jr-card);
  /* The sentence's own type, declared HERE because the link is a sibling and
     inherits from this row rather than from the label. `.jr-textlink` is
     `font: inherit`, so the two read as one line by construction. */
  font-family: inherit; font-weight: 500; font-size: 14.5px; line-height: 1.4;
}
.jr-consent--bad { border-color: var(--jr-red); }
.jr-consent--card > .jr-check--card {
  flex: 0 1 auto;
  min-height: 0; margin: 0; padding: 0;
  border: 0; background: none; border-radius: 0;
  font: inherit;
}

/* The consent tick, in the delivery's bordered card. `.jr-check` on its own is a
   bare flex row — right inside a form group, too small when it IS the act. */
.jr-check--card {
  align-items: center; min-height: 52px; padding: 13px 14px; margin-top: 12px;
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius); background: var(--jr-card);
  font-size: 14.5px; cursor: pointer;
}
.jr-check--card input { width: 22px; height: 22px; }
.jr-check--card.jr-check--bad { border-color: var(--jr-red); }
/* ⭐ D6 · WHAT IS BEING TAKEN ON, INSIDE THE BOX THAT TAKES IT ON. The LMIV
   declaration's second sentence used to sit under the label as a `.jr-note` — a
   class with no rule at all in this file — so it read as a footnote to a legal
   statement instead of as part of one. `align-items` moves to the top because a
   two-line label beside a centred box looks like a mistake. */
.jr-check--card:has(> * > .jr-check__hint) { align-items: flex-start; padding-block: 12px; }
.jr-check__hint {
  display: block; margin-top: 3px;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5;
  color: var(--jr-muted);
}

/* ══════════════════════════════════════════════════════════════════════════
   D6 · THE MENU BLOCK — five screens, from the door to the signature
   ══════════════════════════════════════════════════════════════════════════
   ⭐ ONE SHAPE, USED FIVE TIMES. The delivery draws stations 9–13 out of two
   pieces: a CARD that says where the work has got to, and a row of NUMBERS
   underneath it. `menue_ai` and `menue_review` are the same card with a
   different line in it — decision 2 of the deliverable, in as many words: "kein
   zweiter Review-Flow, keine eigene Bühne für einen Screen, den die meisten nie
   sehen". So there is one set of primitives here and no per-station rule. */

/* ── the waiting card ─────────────────────────────────────────────────────
   ⭐ TINTED, BECAUSE SOMETHING IS HAPPENING IN IT. It is the only block on
   these screens that is not the page's own white, and that is the whole signal:
   the eye finds the thing that is moving without a word being spent on it. */
.jr-wait {
  border-radius: var(--jr-radius); border: 1.5px solid var(--jr-accent-line);
  background: var(--jr-accent-tint); padding: 13px;
}
/* The line that says where the work has got to — the mark and the sentence.
   ⚠️ `margin: 0` IS NOT TIDINESS. This is a `<p>`, so the user-agent gives it
   `1em` top and bottom; inside a 13-px card that is sixteen stray pixels above
   the first thing on the screen and below it. `.jr-say` and `.jr-prov__text`
   carry their own zero for the same reason. */
.jr-wait__now { display: flex; gap: 10px; align-items: center; margin: 0; }
/* And the general sentence under it gets the gap the flex row does not give it. */
.jr-wait__now + .jr-card__text { margin: 8px 0 0; }
/* --- F1 · R2 §B4 · the honest band, INSIDE the box it is about -------------
   ⭐⭐ `ma_time` WAS THE NINTH `.jr-note` AND IS NOT A NOTE. "es ist keine Notiz,
   sondern das ehrliche Band selbst" — the sentence that says how long this takes
   is a property of the wait, so it stands in the tinted card as its own line
   under the phase name, not outside it as a footnote to the screen.
   ⚠️ ITS OWN ZERO MARGIN, for the reason `.jr-wait__now` carries one: a `<p>`
   inside a 13-px card would otherwise spend sixteen user-agent pixels.
   ⚖️ Quieter than the line above it and louder than small print: it qualifies
   the sentence it sits under and is read with it, not searched for. */
.jr-wait__time {
  margin: 6px 0 0;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5;
  color: var(--jr-muted);
}
/* The general sentence keeps its gap whichever of the two it follows. */
.jr-wait__time + .jr-card__text { margin: 8px 0 0; }
.jr-wait__dot {
  flex: 0 0 auto; width: 18px; height: 18px; border-radius: 999px;
  border: 3px solid var(--jr-accent);
  animation: jr-wait-pulse 1.4s ease-in-out infinite;
}
/* ⛔ THE MARK IS `aria-hidden` DECORATION AND THE SENTENCE IS THE FACT. A
   wordless circle in the accessibility tree would be a "graphic" a reader
   announces and nobody can act on; the sentence beside it is already the whole
   information, in the reader's own language.
   ⭐ `.jr-say` IS ITS OWN PRIMITIVE AND NOT `.jr-wait__say`, because three
   screens end on this sentence and only two of them have a waiting card: on
   `allergen_entscheid` it is the conclusion under the four counts, and on
   `menue_bestaetigung` it is the line inside the centred card. A BEM child of a
   block it does not live in is the "one class, two meanings" defect D5 recorded
   — this is the same lesson, met before it could be shipped. The containers
   adjust it; the sentence itself is one rule. */
.jr-say {
  font-family: inherit; font-weight: 700; font-size: 16px; line-height: 1.35;
  color: var(--jr-ink); margin: 0;
}
.jr-wait__now > .jr-say { flex: 1 1 auto; min-width: 0; }
/* ⚖️ THE STILL VERSION OF THE SAME CARD. `menue_review` waits on a PERSON in the
   other tab, so its mark does not breathe: a pulse there would say "we are
   working on it" while the truth is "we are waiting for you". Same card, same
   grid, one word of difference — which is exactly what decision 2 asks for. */
.jr-wait--you .jr-wait__dot { border: 0; background: var(--jr-accent); animation: none; }
@keyframes jr-wait-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }
@media (prefers-reduced-motion: reduce) {
  .jr-wait__dot { animation: none; }
}

/* ── the numbers ──────────────────────────────────────────────────────────
   ⭐⭐ A COUNT IS A TILE, NOT A `label: value` LINE. These are the only measured
   facts on the menu block — files, dishes, similar dishes, open declarations —
   and the delivery sets them big because they are the one thing on the screen
   that is neither a promise nor a forecast.
   ⛔ LABEL AND VALUE STAY TWO ELEMENTS, as everywhere in this journey: no
   language's word order is baked in, and the digits stay 0–9 in Arabic.
   ⚖️ `auto-fit` DECIDES THE COLUMN COUNT BY MEASURING, never by being told the
   station's name — two tiles on a phone, four where there is room. It is the
   same mechanism `.jr-tiles` uses on the review. */
.jr-nums { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; }
.jr-num {
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card); padding: 11px 12px; min-width: 0;
}
/* ⛔ THE NUMBER IS LTR IN EVERY SCRIPT and it is NOT the mono face: a KPI is
   read as a quantity, not as a code, and the heading weight is what makes it
   read that way. `dir="ltr"` sits on the element in the markup as well — this
   is the visual half of the same rule. */
.jr-num__v {
  display: block; font-family: inherit; font-weight: var(--jr-heading-weight);
  font-size: 26px; line-height: 1.05; color: var(--jr-ink);
}
.jr-num__k {
  display: block; margin-top: 4px;
  font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.35;
  color: var(--jr-label); overflow-wrap: anywhere;
}
/* The one tile that is a QUESTION rather than a report: dishes that need the
   owner, declarations that are still open. It is tinted, never red — nothing
   here has failed. */
.jr-num--open { border-color: var(--jr-accent-line); background: var(--jr-accent-tint); }
.jr-num--open .jr-num__v { color: var(--jr-accent-ink); }
/* Inside the tinted waiting card the tiles need its own border colour, or two
   greys sit on a tinted ground and read as a mistake. */
.jr-wait .jr-nums { margin-top: 12px; }
.jr-wait .jr-num { border-color: var(--jr-accent-line); }

/* ── the band ─────────────────────────────────────────────────────────────
   ⭐⭐ "EIN BAND, KEIN COUNTDOWN" — the delivery's own words, and the numerals
   beside them are a RANGE. A countdown would claim a precision that eleven
   measured imports do not support, and the moment it reached zero with the
   worker still running it would turn a working import into an apparent failure.
   ⛔ THE FIGURE CARRIES NO UNIT WORD. `3 × 0:30–1:00` is the colon form D5 chose
   for the build clock, for the same reason: it needs no word in any of the five
   languages, and the sentence above it (`ma_time`) already says "half a minute
   to a minute" in words that were translated five times. */
.jr-band { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; margin: 4px 0 0; }
.jr-band__k { font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.4; color: var(--jr-label); }
.jr-band__v { font: 500 12.5px/1.4 var(--jr-mono); color: var(--jr-muted); }

/* ── the other window ─────────────────────────────────────────────────────
   ⭐ STATION 13 POINTS AT A PLACE, and the delivery centres it for that reason:
   it is the only card in the journey whose subject is somewhere else.
   ⛔ AND IT DOES NOT QUOTE THE OTHER WINDOW'S BUTTON. The prototype sets the
   word BESTÄTIGEN in large tracked capitals here; that word is the tenant
   module's own label, rendered in the TENANT's admin language, and freezing the
   German of it into five languages would be a lie in four of them. It is also
   `letter-spacing` on a line whose joins Arabic would break. The place is named
   by `mb_where` and described by `mb_s_*`, both of which were translated. */
.jr-where { text-align: center; }
.jr-where__k {
  display: block; font-family: inherit; font-weight: 500; font-size: 12px; line-height: 1.35;
  color: var(--jr-label); text-transform: uppercase; letter-spacing: .09em;
}
/* ⛔ AND ARABIC GETS NEITHER THE TRACKING NOR THE CAPITALS — spacing breaks the
   letter joins and Arabic has no case, so `uppercase` is a no-op that only ever
   costs. The same pair D5's tile headings switch off, one section up. */
body.jr-page[dir="rtl"] .jr-where__k { letter-spacing: 0; text-transform: none; }
.jr-where > .jr-say { margin-top: 8px; }
/* ⚖️ The dated act, centred with the card it is in — see the markup's own note.
   A modifier rather than a `.jr-where .jr-kv` descendant rule, because the day a
   second centred card appears the meaning travels with the class instead of
   with the ancestor. */
.jr-kv--centre { justify-content: center; margin-top: 10px; }
/* The conclusion under the four counts of the declaration — it follows a grid,
   so it needs the gap that grid does not give it. */
.jr-nums + .jr-say, .jr-note + .jr-say { margin-top: 14px; }

/* ── the width, on these five screens ─────────────────────────────────────
   ⛔ ONE OF FIVE, AND THE OTHER FOUR ARE THE RULE WORKING. A station joins
   `$shellWide` in the same commit as a layout that USES the width — `dpa` was
   D5's exception, and D6 has four more: `menue_upload` is a headline, a card and
   a button; `menue_ai` and `menue_review` are one card whose row of tiles is
   already `auto-fit` inside it; `menue_bestaetigung` is one centred card. A
   1120-px shell around any of them is the "very wide single column" this file's
   own `--wide` note calls worse than a centred phone column.
   ⭐ `allergen_entscheid` IS THE ONE THAT EARNS IT: four independent counts — a
   SET and not a sequence, which is the same argument that put the verdict list
   in two columns on `final_validation`. Its grid is `auto-fit`, so it needs no
   width rule of its own at all: the tiles run out of room and the browser
   answers. That is why there is no `.jr-nums` media query anywhere in this
   file — a rule naming the station would be a second place to keep in step.

   🔴 G1 · ALL FIVE TAKE THE SHEET NOW, and this note's ⭐ half is why nothing
   below it moved. The four that "do not earn it" were being asked the
   COMPOSITION question in order to answer the WIDTH question; the delivery
   answers the width itself, at 1072 px, on all five boards. `allergen_entscheid`
   also loses the `journey_view_legal_has_counts()` condition the PAGE carried —
   the grid keeps it, which is the only thing that question could ever decide.
   ⚠️ AND THE TILE ROWS ARE THE PROOF THE WIDTH IS NOT DEAD HERE: measured at
   1440, the three `.jr-num` tiles of the counts composition stand side by side
   at 340 px each, on `auto-fit` alone and with no rule naming a station. */

/* ══════════════════════════════════════════════════════════════════════════
   D7 · THE END — from the nine criteria to the poster
   ══════════════════════════════════════════════════════════════════════════
   Four screens, and three of them are the SAME two blocks at different sizes:
   the criteria list (which D5 already built) and the launch output (link, code,
   actions). The fourth is the journey's one poster.

   ⛔ NOT ONE RULE BELOW ASKS FOR A STATION BY NAME — D5's rule, D6's rule, and
   the reason `.jr-checks--verdict` could be handed nine rows without a line of
   new layout code. Everything asks about CONTENT.
   ⛔ AND EVERY TYPE RULE IS THREE LONGHANDS PLUS `font-family: inherit`, because
   D3 measured what the `font:` shorthand with `inherit` in it does: nothing, in
   fifty-seven rules at once. */

/* ── the overline ─────────────────────────────────────────────────────────
   ⭐ THE DELIVERY'S QUIET BLOCK LABEL (`gl`), AS ONE PRIMITIVE. It names the
   thing under it — "Bestell-Link", "Startliste", "Was jetzt steht",
   "Empfehlungen" — without competing with the page's own headline, which is why
   it is a `span` and not a fourth heading level: four of these on one screen
   would be four headings in a screen reader's outline for four labels.
   ⚠️ THIS IS THE THIRD PLACE THIS SHAPE APPEARS AND THE FIRST TIME IT IS A
   CLASS. `.jr-review--tile .jr-h2` (D5) and `.jr-where__k` (D6) draw the same
   thing by other routes — one because it is a real heading inside a tile, the
   other because it is a block's own child. Both are left alone: rewriting two
   shipped screens to reach one class name is a cosmetic gain, and the recorded
   lesson of this very batch is that moving working markup to tidy a NAME is how
   `.jr-live` happened. Named, not merged. */
.jr-over {
  display: block; margin: 0 0 7px;
  font-family: inherit; font-weight: 700; font-size: 11.5px; line-height: 1.3;
  letter-spacing: .08em; text-transform: uppercase; color: var(--jr-label);
}
/* ⚠️ ARABIC KEEPS ITS LETTERS AND HAS NO CASE. Tracking breaks the joins and
   clips the descenders; `uppercase` is a no-op that only ever costs. (D2's
   universal `letter-spacing: normal !important` already wins here — this line is
   the record of the pair, exactly as D5 and D6 wrote theirs.) */
body.jr-page[dir="rtl"] .jr-over { letter-spacing: 0; text-transform: none; }

/* ── the criteria, and the one row that became a control ──────────────────
   The nine are `.jr-checks--verdict`, unchanged from D5. Only the row that is
   also a CONTROL (`notification_channel`, deferred item 129) needs anything:
   inside the grouped card it keeps the card's padding, and inside the
   two-column desktop grid it has to SPAN — a form squeezed into half a row puts
   a 44-px button under a 200-px column. */
.jr-checks--verdict > .jr-check-row--action {
  grid-column: 1 / -1;
  background: var(--jr-accent-tint);
}
/* ⛔ THE TINT IS THE ACCENT, NEVER THE ERROR COLOUR — nothing here has failed,
   one thing simply has not been answered yet. Same decision as `.jr-num--open`. */
.jr-check-row--action .jr-check-row__note { color: var(--jr-muted); }

/* The recommendations: quieter than the criteria, and they KEEP their state.
   ⚖️ The delivery draws them as three flat chips; the engine measures a real
   verdict for each (`logo_present`, `social_links`, `online_payments`), and a
   chip would tell an owner who already added their Instagram to add it, for
   ever. Smaller type and a smaller mark say "secondary" without throwing the
   fact away. */
.jr-adv { display: flex; flex-wrap: wrap; gap: 2px 10px; align-items: baseline; margin-top: 18px; }
.jr-adv > .jr-over { margin-bottom: 0; }
.jr-adv__note {
  margin: 0; min-width: 0;
  font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.4;
  color: var(--jr-faint); overflow-wrap: anywhere;
}
.jr-checks--advisory > .jr-check-row { padding: 8px 14px; }
.jr-checks--advisory .jr-check-row__text { font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.4; }
.jr-checks--advisory .jr-check-row__mark { width: 16px; height: 16px; font-size: 10px; }

/* The card that says the link is not there yet. It is a statement about
   something ABSENT, so it wears the page's quiet ground rather than the white of
   a card that holds content. */
.jr-card--quiet { background: var(--jr-quiet); margin-top: 16px; }
/* --- F1 · the record of an act that is already on file --------------------
   ⭐ A RECEIPT, NOT AN ACHIEVEMENT. The ground is the page's own neutral and the
   only green on it is the tick, which is R1's ruling for the DPA's second act:
   "Grün als Fläche ist in dieser Reise dem Erfolgsstreifen vorbehalten." The
   mark is 22 px and its glyph comes from the stylesheet, like every other mark
   here — the sentence beside it carries the meaning in the reader's language. */
.jr-record { display: flex; gap: 11px; align-items: flex-start; }
.jr-record__body { flex: 1 1 auto; min-width: 0; }
.jr-record__tick {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 999px;
  background: var(--jr-green-soft); color: var(--jr-green-ink);
  display: grid; place-items: center;
  font-family: inherit; font-weight: 700; font-size: 12px; line-height: 1;
}
.jr-record__tick::before { content: "\2713"; }
/* ⚠️ `.jr-card__text` carries a 10-px bottom margin for the case where something
   follows it. When it is the last thing in the card, that margin is a stray gap
   inside the border — visible against 14 px of padding. */
.jr-card__text--last { margin-bottom: 0; }

/* ── the launch output ────────────────────────────────────────────────────
   ⭐ ONE BLOCK, TWO SCALES. The link and its code are the same three things on
   both screens; `--big` is the poster's half of it. */
.jr-out { margin-top: 16px; }
/* ⛔ THE URL IS THE ONE STRING ON THIS JOURNEY AN OWNER COPIES BY HAND, so it is
   shown whole rather than behind a word — and `anywhere` is what keeps a
   subdomain plus `/menu/menu.php` from extending an RTL document's scroll width
   (W1's measured 10 389 px). `dir="ltr"` sits on the element in the markup too. */
.jr-out__url {
  display: block; margin: 0 0 14px;
  font: 700 14px/1.45 var(--jr-mono);
  color: var(--jr-ink); text-decoration: underline; text-underline-offset: 3px;
  overflow-wrap: anywhere;
}
.jr-out--big .jr-out__url { font-size: 15px; }
/* The code beside its sentence, and it WRAPS: at 390 px a 92-px square plus a
   sentence plus two buttons is not a row, and a `flex-basis` on the text column
   is what lets the browser decide that instead of a media query. */
.jr-out__row { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.jr-out__say { flex: 1 1 190px; min-width: 0; }
.jr-out__t { margin: 0; font-family: inherit; font-weight: 700; font-size: 14px; line-height: 1.35; }
.jr-out--big .jr-out__t { font-size: 15px; }
.jr-out__s { margin: 4px 0 0; font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5; color: var(--jr-muted); }
.jr-out__acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* ⛔ THE CODE IS A REAL PIXEL SIZE, NOT `max-width: 100%` OF WHATEVER IS THERE.
   It is photographed off a phone by a guest and printed onto a table card; a QR
   that reflows to 40 px scans badly, and one that fills a 460-px column pushes
   its own sentence off the fold. The delivery's two numbers, kept: 92 beside the
   checklist, 118 on the poster. `.jr-qr`'s own 240 stays for any future screen
   that shows the code on its own. */
.jr-out__qr {
  flex: 0 0 auto; width: 92px; height: 92px; margin: 0;
  border-radius: var(--jr-radius); background: var(--jr-card);
  border: 1.5px solid var(--jr-line); padding: 4px;
}
.jr-out--big .jr-out__qr { width: 118px; height: 118px; }

/* ── the launch list ──────────────────────────────────────────────────────
   ⭐ THE COUNT SITS ON THE LIST'S OWN LINE, where a progress figure belongs:
   before the list, not under it. Label and value stay two elements — `--end`
   only decides which of the two the eye meets first. */
.jr-listhead {
  display: flex; flex-wrap: wrap; gap: 4px 12px;
  align-items: baseline; justify-content: space-between; margin-top: 20px;
}
.jr-listhead > .jr-over { margin-bottom: 0; }
.jr-kv--end { flex: 0 0 auto; }
.jr-kv--end > .jr-kv__v { font-family: inherit; font-weight: 700; font-size: 13px; line-height: 1.3; color: var(--jr-muted); }

/* The ten rows as the delivery's grouped card, like the criteria above them. */
.jr-tasks {
  border: 1.5px solid var(--jr-line); border-radius: var(--jr-radius);
  background: var(--jr-card); overflow: hidden;
}
.jr-task { padding: 12px 14px; }
.jr-task + .jr-task { border-block-start: 1.5px solid var(--jr-line-soft); }
/* ⭐ THE ONE ROW THAT CANNOT BE SKIPPED, TINTED — the delivery's emphasis, in the
   accent and never in the error colour: nothing has failed, one thing has to be
   answered. The modifier comes from campaign_lead_launch_unskippable_tasks(),
   the same list the missing "Später" button comes from. */
.jr-task--must { background: var(--jr-accent-tint); }
.jr-task--must .jr-task__label { font-weight: 700; }
/* ⭐ AND EVERY LINK IN A ROW GETS A THUMB'S WORTH OF BOX WITHOUT MOVING ONE PIXEL
   OF INK — D5's `.jr-edit` trick, measured against the same 44-px floor. The help
   pages, the share message and the two store links are all things an owner is
   meant to TAP on a phone, and all of them were inline text. Padding plus the
   matching negative margin leaves the baseline-aligned row exactly where it was.
   🔴 AND 14 IS A MEASURED NUMBER, NOT A ROUND ONE. 12 was the first guess and the
   browser answered 41 px: an INLINE box is the font's own content box, not its
   line-height, so "App Store", "Google Play" and the WhatsApp line — 16-px text
   inside a bare `<p>` — measured 17 px of content, not 20. Only the row's own
   label (14 px, and a block-level flex item, so its box IS its line-height)
   reached 44. Three of the four failed by three pixels, in five languages and
   three viewports, and no markup assertion could have said so. */
.jr-task .jr-link { padding-block: 14px; margin-block: -14px; }

/* ── E2 · the launch list's desktop break-out ─────────────────────────────
   ⭐⭐ THE OTHER HALF OF ITEM 6, AND THE ONE THAT WAS NOT BUILT AT ALL. D7
   measured this station and refused it the width in the same breath, and wrote
   down why: "ten rows stretch and do not lay out". Measured again before this
   rule was written — 460-px column at 834 AND at 1440, ten rows in one column,
   1793 px of page, with 980 pixels of nothing beside it on a desktop.

   ⛔ AND THE ARGUMENT IS BORROWED, NOT INVENTED. It is `readiness_ok`'s: these
   are INDEPENDENT things and they read as a SET rather than as a sequence, which
   is what makes splitting them honest — a sequence would have to read down.
   `.jr-checks--verdict` earned two columns on exactly that reasoning in D5, at
   exactly this breakpoint, with exactly this `:has(> :nth-child(4))` question,
   and the locked composition of THIS screen renders that very list. So the two
   halves of one station now lay out by one rule each, and both rules ask how
   many rows there are rather than which station is on screen.

   ⚠️ THE `:has()` IS NOT DECORATION. A ledger whose migration has not run draws
   an EMPTY list, and a journey mid-flight can legitimately draw fewer; two
   columns around one row is the defect, not the layout. Same guard, same number
   as the criteria list.
   ⛔ AND THE SEPARATORS FOLLOW THE GRID, not the source order: in two columns
   the second child starts a column of its own and must lose its top rule, and
   every even child gains an inline-start one. Logical properties, so Arabic puts
   the second column where Arabic puts it. */
@media (min-width: 834px) {
  .jr-shell--wide .jr-tasks:has(> :nth-child(4)) {
    display: grid; grid-template-columns: 1fr 1fr; gap: 0; align-items: start;
  }
  .jr-shell--wide .jr-tasks:has(> :nth-child(4)) > .jr-task:nth-child(2) { border-block-start: 0; }
  .jr-shell--wide .jr-tasks:has(> :nth-child(4)) > .jr-task:nth-child(even) {
    border-inline-start: 1.5px solid var(--jr-line-soft);
  }
}

/* ── the poster ───────────────────────────────────────────────────────────
   ⭐⭐ THE ONE FULL RED FIELD OF THE WHOLE JOURNEY (`ENTSCHEIDUNGEN.md` §6). It
   bleeds to the edges of the shell, because a poster with a 20-px white gutter
   around it is a box and not a field. The 20 px is `.jr-body`'s own inline
   padding — the one number in this file that has to be written twice, and it is
   written here rather than turned into a token because a token would invite a
   second consumer to change it for both.
   🔴 AND THE NEGATIVE MARGIN IS INLINE-LOGICAL, NEVER `left`. W1 measured what a
   physical negative offset does inside an RTL document: it EXTENDS the scrollable
   area, and a 390-px Arabic page came back 10 389 px wide. `margin-inline`
   mirrors instead of extending, and `.jr-shell`'s `overflow: clip` is the second
   half of the guarantee. */
.jr-poster {
  margin-block: 4px 0; margin-inline: -20px;
  padding: clamp(26px, 4.6vw, 48px) clamp(18px, 3vw, 34px) clamp(22px, 3.6vw, 38px);
  background: var(--jr-accent); color: #fff;
}
.jr-poster__mark {
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 999px;
  background: #fff; color: var(--jr-accent);
  font-family: inherit; font-weight: 700; font-size: 17px; line-height: 1;
}
.jr-poster__mark::before { content: "\2713"; }
/* --- F1 · R5 · the one place the journey names its own phase --------------
   ⭐ WHITE IN THE RED FIELD, and it is the phase band's own type treatment
   (`.jr-phases__name`: 10.5 px, 700, uppercase, .1em) in the poster's ink — the
   same word in the same voice, so the screen that replaces the band does not
   invent a second way of saying it.
   ⚠️ `display: block` because it is a `<span>` between a grid mark and an `h1`;
   the 16-px top margin the headline carries measures from this element now. */
.jr-poster__phase {
  display: block; margin: 18px 0 0;
  font-family: inherit; font-weight: 700; font-size: 10.5px; line-height: 1.3;
  letter-spacing: .1em; text-transform: uppercase; color: #fff;
}
.jr-poster__phase + .jr-poster__t { margin-top: 6px; }
/* ⛔ `9vw` IS A VIEWPORT MEASURE, AND THAT IS WHY `abgeschlossen` IS `--wide`. At
   1280 px this headline is 92 px of type; inside a 460-px column it would be a
   word and a half per line. The width is granted for exactly this.
   🔴 THE LEADING IS 1.1 AND THE DELIVERY SAYS .9 — MEASURED, NOT PREFERRED. At
   .9 the headline's ink sits OUTSIDE its own box: 3 px at 42 px and 8 px at 92,
   read off a real browser, with 12 px of margin between it and the sentence
   underneath. The ladder was walked rather than guessed —
   .9→8 · 1.0→4 · 1.05→1 · 1.1→0 at the poster size — and 1.1 is the tightest
   ratio at which Archivo's own ink fits the box it is given. A display headline
   whose descenders reach into the line below is the defect the delivery was
   drawing around, not the effect it wanted. */
.jr-poster__t {
  margin: 16px 0 0;
  font-family: inherit; font-weight: var(--jr-heading-weight);
  font-size: clamp(42px, 9vw, 92px); line-height: 1.1; letter-spacing: -.02em;
  color: #fff; overflow-wrap: anywhere;
}
.jr-poster__s {
  margin: 12px 0 0; max-width: 26ch;
  font-family: inherit; font-weight: 600;
  font-size: clamp(17px, 2.4vw, 24px); line-height: 1.24; color: #fff;
}
/* 🔴🔴 AND ARABIC GETS `normal`, WHICH IS THE THIRD TIME THIS PLATFORM HAS PAID
   FOR CAIRO'S LEADING. D3's RTL floor sets 1.7 on everything — right for running
   text, a screen and a half tall for a 92-px headline — so this rule exists to
   take it back. My first attempt took it back to 1.12 and the browser answered
   with 35 px of ink outside the box at 92 px. The ladder says why: for Cairo,
   1.0→40 · 1.1→36 · 1.2→31 · 1.25→29, and `normal`→0. There is NO ratio that
   fits; Cairo's own metric is the only value that does, because the face reserves
   room for marks Latin does not have. ⇒ `normal`, measured, not chosen.
   ⚠️ The tracking goes with it — D2's universal `letter-spacing: normal
   !important` already removes it, and this line is the record of the pair. */
body.jr-page[dir="rtl"] .jr-poster__t { line-height: normal; letter-spacing: 0; }
body.jr-page[dir="rtl"] .jr-poster__s { line-height: 1.45; }

/* The receipt under it — four EXISTING criteria, no invented figure, no
   confetti. `auto-fit` again: two columns where there is room, one on a phone,
   decided by measuring and never by naming the station. */
.jr-built { margin-top: 20px; }
.jr-checks--built { border: 0; border-radius: 0; background: transparent; }
.jr-checks--built > .jr-check-row { padding: 7px 0; border-block-start: 0; }
@media (min-width: 560px) {
  .jr-checks--built { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0 18px; }
}

/* ── station 2 · the receipt, centred ─────────────────────────────────────
   ⭐ THE ONLY CENTRED SCREEN BEFORE THE POSTER, and the centring IS the message:
   every other station is a left-aligned column of work, and this one has no work
   in it. */
.jr-hail { text-align: center; }
.jr-hail__mark {
  display: inline-grid; place-items: center;
  width: 54px; height: 54px; border-radius: 17px; margin-bottom: 14px;
  background: var(--jr-green-soft); color: var(--jr-green-ink);
  font-family: inherit; font-weight: 700; font-size: 26px; line-height: 1;
}
.jr-hail__mark::before { content: "\2713"; }
.jr-hail > .jr-lede { max-width: 40ch; margin-inline: auto; }
/* 🔴 05.09.2026 · AND `hidden` HAS TO BE SAID FOR THIS ONE TOO — third time in
   this file, same reason (§N8 above, and `.jr-logo-grid[hidden]`). The receipt
   carries TWO ledes while a WhatsApp copy of the link is still in flight: the
   true one, and the one that becomes true only if a handset acknowledges the
   message. The hidden half is a sentence that is NOT true yet, so its `hidden`
   may not depend on a UA default that any later `display` rule on `.jr-lede`
   would silently beat. */
.jr-lede[hidden] { display: none; }
/* ⚠️ AND THE NOTE INSIDE IT IS NOT CENTRED. Two sentences and a dated pair are
   running text; a centred paragraph has a ragged left edge in five languages, and
   a centred `.jr-kv` would let its label and its value drift apart. `start`
   mirrors with the document, which `left` would not. */
.jr-hail > .jr-card { text-align: start; }

/* ── the width, on these four screens ─────────────────────────────────────
   ⛔ TWO OF FOUR, AND THE OTHER TWO ARE THE RULE WORKING.
   ⭐ `readiness_ok` EARNS IT WITHOUT ONE NEW LINE: it renders the same
   `.jr-checks--verdict` D5 taught to split at four rows or more, and nine
   criteria are a SET and not a sequence. The rule that lays them out is already
   written above — asked about the number of rows, never about which station is
   on screen.
   ⭐ `abgeschlossen` EARNS IT FOR THE HEADLINE AND THE RECEIPT: `9vw` is a
   viewport measure (see `.jr-poster__t`), and the receipt is an `auto-fit` grid
   that answers the width by measuring itself. BOTH of its compositions use it —
   the locked one draws the same nine criteria — so there is no `:has()` question
   to ask here, unlike `allergen_entscheid` in D6.
   ⛔ `gesichert` IS A MARK, TWO SENTENCES AND A BOXED DATE, and `launch_station`
   is ten rows whose desktop break-out the delivery's own README defers to Welle 2
   (§6.6). A 1120-px shell around either is the "very wide single column" this
   file's `--wide` note calls worse than a centred phone column. Both are held by
   a negative in five languages × three viewports.

   🔴 G1 · BOTH TAKE THE SHEET — `launch_station` since E2, `gesichert` now — and
   the receipt is the one screen where this file already carried the answer. The
   delivery's ONE stated width instruction is `max-width: 40ch` on this screen's
   lede, and `.jr-hail > .jr-lede` above has shipped it since D7: a receipt on a
   wide sheet is a centred column at the phone's own measure, not a stretched
   one. That rule is what makes the sheet safe to grant here, and it needed no
   line added — the mark, the headline and the lede centre themselves, the note
   stays `text-align: start` because it is running text, and 1120 px of sheet
   changes where the card sits, not how wide the sentence reads.
   ⚖️ The `launch_station` half of the paragraph above was already superseded by
   E2, which built the ten-row break-out the README defers; only the sentence
   about `gesichert` was still live, and it is this one that replaces it. */

/* ══════════════════════════════════════════════════════════════════════════
   WELLE 2 · E1 — the screens where something is NOT going well
   ══════════════════════════════════════════════════════════════════════════
   ⭐⭐ THE FIRST SCREENS OF THIS JOURNEY THE DELIVERY DOES NOT DRAW. `reise.dc.html`
   carries twenty-one `data-screen` sections — the entry, sixteen stations and four
   in-between states of stations — and not one of the seven states below. So there
   was nothing to copy, and the rule that replaces copying is the one D1–D7 wrote:
   ASK ABOUT THE CONTENT, NEVER ABOUT THE NAME.

   The content answers with three questions, not seven:

     1. Is there work on this screen?  No — none of the seven. `gesichert` is the
        one shipped screen with no work in it and it is CENTRED for exactly that
        reason (`.jr-hail`), so these are centred too. Same argument, same shape,
        and the reader who has seen one has seen the other.
     2. Whose problem is it?  Three answers, and journey_view_notice_copy() writes
        them down: the LINK (`link`), the JOURNEY IS OVER (`ended`), SOMEBODY ELSE
        IS HOLDING IT (`waiting`). That is the whole taxonomy, and it is why there
        are three marks here and not seven.
     3. Does the screen invite a message?  Two of seven, and only where the screen's
        own sentence already does — the vocabulary carries `ways` for it.

   ⛔ AND EVERY TYPOGRAPHIC DECISION IS BORROWED, NOT REMADE. `.jr-h1` and
   `.jr-lede` come with D3's long-hand `font-family` (the `font:` shorthand with
   `inherit` in it that killed fifty-seven rules), with D3's RTL floor and with
   D7's measured heading leading. A fresh headline rule here would have been a
   fresh chance to repeat all three.
   ═══════════════════════════════════════════════════════════════════════════ */
.jr-halt { text-align: center; }
/* ⭐ THE MARK IS THE MESSAGE, and it is the same 54-px square `.jr-hail__mark`
   above declares: one shape that means "this is a statement, not a task". Only
   its ground and its glyph change with the tone.
   🪤 CORRECTED N1, 21.08.2026: this used to read "the same square `gesichert`
   WEARS". It does not wear one — F1·R1 took the green disc off the receipt on
   18.08 and `journey_page_harness.php` asserts its absence. `.jr-hail__mark`
   above is therefore drawn by nothing today; it is kept because THIS rule is its
   twin and the two are meant to stay one shape, and because the disc is a
   decision that can be revisited, not a bug. ⛔ But no comment may say the
   receipt carries it. */
.jr-halt__mark {
  display: inline-grid; place-items: center;
  width: 54px; height: 54px; border-radius: 17px; margin-bottom: 14px;
  font-family: inherit; font-weight: 700; font-size: 26px; line-height: 1;
}
/* ⚠️ 40ch, LIKE `.jr-hail` — a centred paragraph running the full width of a
   460-px card has a ragged left edge in five languages. */
.jr-halt > .jr-lede { max-width: 40ch; margin-inline: auto; }

/* --- tone 1 · the LINK is the problem, the journey is intact --------------
   Amber, which on this platform means "look at this", never "this failed":
   `.jr-banner` (the plain tone), `.jr-card--warn` and `.jr-check-row--blocked`
   all use it for a thing that is in the way rather than broken. An expired link
   is the purest example — nothing is lost and nothing went wrong.
   ⚖️ AND NOT THE ERROR RED. D7 recorded that error and warning colour are
   placeholders until Welle 2 decides them (item 4 of the delivery's own order:
   "Feld- und Transportfehler als zwei sichtbar verschiedene Dinge"). Spending
   the red here would spend a decision this batch is not the one to make. */
.jr-halt--link .jr-halt__mark {
  background: var(--jr-amber-soft); color: var(--jr-amber-ink);
  border: 1.5px solid var(--jr-amber-line);
}
.jr-halt--link .jr-halt__mark::before { content: "!"; }

/* --- tone 2 · the JOURNEY IS OVER, and that is not a failure --------------
   ⭐⭐ THE TICK, AND IT IS AN ARGUMENT AND NOT A DECORATION. `x_stopped_s` says
   in five languages "Das war Ihre Entscheidung, kein Fehler" — and a screen that
   says so in words while wearing the colour of a broken thing is a screen that
   disagrees with itself. A stop is a COMPLETED act, so it wears the same
   `\2713` every finished criterion on this journey wears.
   ⛔ IN THE PAGE'S QUIET INK, NEVER IN GREEN. `.jr-hail__mark` is green because
   `gesichert` is an achievement; ending the journey is not one, and congratulating
   somebody for leaving would be worse than the grey screen this replaces. */
.jr-halt--ended .jr-halt__mark {
  background: var(--jr-quiet); color: var(--jr-muted);
  border: 1.5px solid var(--jr-line);
}
.jr-halt--ended .jr-halt__mark::before { content: "\2713"; }

/* --- tone 3 · SOMEBODY ELSE IS HOLDING IT ---------------------------------
   The accent tint, which this stylesheet already uses three times for "nothing
   has failed, something is simply still open": `.jr-num--open`, `.jr-task--must`
   and `.jr-check-row--action`. An operator takeover, a stalled job a human is
   already looking at, and a station we have not built yet are all that same
   fact — and `fehlgeschlagen` belongs here rather than under an error mark
   because its own copy says the job retries itself and decision 4 forbids a
   retry button for that reason.
   🔴🔴 THE GLYPH IS NUDGED, AND THE NUMBER WAS WALKED — IT WAS WRONG WHEN IT WAS
   GUESSED. `\2026` sits ON the baseline, so `place-items: center` centres its
   BOX and leaves its INK low: the same class of defect as D7's inline tap
   targets, one glyph along. The ladder was read off a real browser at 3× by
   cropping the mark and finding the ink rows —
     0 → +7.00 · −.2 → +2.00 · −.25 → +1.00 · −.26 → 0.00 · −.27 → 0.00 ·
     −.28 → 0.00 · −.3 → −1.00 · −.34 → −2.00 · −.4 → −3.00 · −.5 → −6.00
   (CSS px, positive = ink below the box's centre). `-.34em` was the first guess
   and it overshot by two pixels; the flat band is −.26…−.28 and this is its
   middle. ⛔ The lift is on the PSEUDO-ELEMENT, so the box every gate measures
   stays exactly 54 px — a nudge on the mark itself would move the whole square
   and the measurement would still say 54. */
.jr-halt--waiting .jr-halt__mark {
  background: var(--jr-accent-tint); color: var(--jr-accent-ink);
  border: 1.5px solid var(--jr-accent-line);
}
.jr-halt--waiting .jr-halt__mark::before { content: "\2026"; position: relative; top: -.27em; }

/* --- the two ways, where the screen's own sentence invites them -----------
   ⛔ `.jr-support` IS REUSED WHOLE, and that is deliberate: the support screen
   has shipped since P7.1 with two 52-px links and a rule that there is never a
   telephone number on them. `gestoppt` now offers the same two ways, which is
   also the ANSWER to "do not build a second stop page": /stopp/ is the reminder
   ladder's off switch (it asks, and its POST acts) and this is what a person who
   already pressed it sees when they open their journey link. Different moment,
   different credential — and now the same two ways out of both, word for word.
   ⚠️ AND THE BLOCK IS LEFT-ALIGNED INSIDE A CENTRED SCREEN, exactly like
   `.jr-hail > .jr-card`: `s_human` and `s_noretry` are running text, and running
   text centred over three lines has a ragged edge in every language. `start`
   mirrors with the document; `left` would not. */
.jr-halt > .jr-support { text-align: start; max-width: 34rem; margin-inline: auto; }

/* ── E2 · the two lines the STOP page brings with it ──────────────────────
   ⛔ WRITTEN BECAUSE THE PAGE EMITS THEM, AND WRITTEN IN THE SAME COMMIT.
   `/3-monate-kostenlos/stopp/` now wears this stylesheet (item 5 of the
   delivery's Welle-2 order) and it has exactly two things the journey does not:
   a legal footer, because the journey's own shell has none to borrow, and the
   second action beside the off switch. Two class names — and E1 shipped a class
   with no rule inside a single batch and watched it render at the browser's
   default 16 px, LARGER than the sentence above it. So they are declared here
   rather than left to inherit, and the browser gate asks their computed size.
   ⚖️ Both are the journey's own values, not new ones: the footnote is the
   `.jr-hint` scale in the page's faint ink, and the alternative action is the
   `--quiet` primary at the same 56-px thumb reach as the loud one. */
.jr-stop-legal {
  margin: 22px 0 0;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5;
  color: var(--jr-faint); text-align: center;
}
.jr-stop-legal a { color: var(--jr-faint); }
.jr-stop-alt { margin-top: 10px; }

/* ── the quiet head of a return (E1) ──────────────────────────────────────
   ⭐⭐ THE MOST REPEATED MOMENT OF THE WHOLE JOURNEY AND THE ONLY ONE WITHOUT A
   SENTENCE — `ENTSCHEIDUNGEN.md`, decision 4, in those words. Every one of the
   four reminder mails lands on a station screen, and until this rule a returning
   owner got exactly what a first-time visitor got: a form, mid-journey, with no
   acknowledgement that they had ever been here. The three keys have existed in
   five languages since P7.1 and nothing rendered them.

   ⛔ A HEAD, NOT A SCREEN — decision 4 again, and it is the whole design. An
   interstitial saying "welcome back" with a "continue" button is one more tap
   between a person and the work they came back to do, and the work is already on
   the screen behind it.

   ⚠️ IT SHARES THE SUCCESS STRIPE'S SLOT, and the two are mutually exclusive by
   construction: `.jr-ok` speaks when the SERVER answered `saved`, this speaks
   when nothing happened and somebody simply arrived. Both answer "what just
   happened"; two of them at once would be two answers.
   ⚖️ AND IT IS QUIETER THAN THE STRIPE ON PURPOSE. Arriving is not an
   achievement — no green, no tick, no uppercase label. A rule on the inline
   start edge and the page's own quiet ground: present, and impossible to mistake
   for something that needs doing. */
/* 🔴 F1 · R5 — and it moved into `<main>` WITH the stripe, because "it shares
   the success stripe's slot" is the whole argument for where it stands. Same
   inset correction as `.jr-ok` above. */
.jr-resume {
  flex: 0 0 auto; margin: 0 0 12px;
  padding: 9px 13px; border-radius: var(--jr-radius);
  background: var(--jr-quiet);
  /* logical, so Arabic gets the rule on its own leading edge and not a second one.
     🔴 MEASURED, NOT PREFERRED: with a physical `border-left` the four LTR
     languages render byte-identically and only Arabic moves the rule to the END
     of the line — 3 of 15 views, and no source assertion sees it. */
  border-inline-start: 3px solid var(--jr-line-strong);
}
.jr-resume__t {
  margin: 0;
  font-family: inherit; font-weight: 700; font-size: 13.5px; line-height: 1.35;
  color: var(--jr-ink);
}
.jr-resume__s {
  margin: 2px 0 0;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5;
  color: var(--jr-muted);
}

/* ── E1 · when the send button comes back ─────────────────────────────────
   ⭐⭐ THE OWNER'S OWN DECISION (17.08.2026), and it is a LABEL AND A VALUE, not a
   sentence with a time in it — `public-i18n.js` writes textContent and
   substitutes nothing, so a string carrying a placeholder would ship its braces
   to a customer. Same construction as `g_valid` + the date on `gesichert`.
   🔴🔴 AND IT HAS A RULE, WHICH IS THE WHOLE POINT OF WRITING THIS ONE DOWN. The
   first version of this line shipped with no rule at all and rendered at the
   browser's default 16 px — LARGER than the row's own sentence three pixels
   above it — and outside the row's 14-px indent, so it hung off the left edge of
   its own tinted box. Seen in a Turkish phone screenshot; every markup assertion
   was green, because the element was present and nothing was clipped. That is
   `.jr-note`'s defect (eight consumers, three batches, still no rule) reproduced
   inside one batch, and the browser gate now asks the computed size so it cannot
   happen again silently. */
.jr-vrow__again {
  display: flex; flex-wrap: wrap; gap: 2px 8px; align-items: baseline;
  margin: 6px 0 0;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5;
  color: var(--jr-muted);
}
/* The open row indents everything it owns; this belongs to it. */
.jr-vrow--open .jr-vrow__again { padding-inline: 14px; padding-block-end: 2px; }
/* ⛔ A CLOCK IS A MACHINE STRING A HUMAN READS BACK: LTR in every language (the
   attribute is on the element too), tabular figures so it cannot jitter, and the
   digits stay 0–9 in Arabic — the standing rule for every number on this
   journey. */
.jr-vrow__at,
.jr-vrow__deadline {
  font: 600 12.5px/1.5 var(--jr-mono); color: var(--jr-ink);
  font-variant-numeric: tabular-nums;
}

/* ══════════════════════════════════════════════════════════════════════════
   THE DESKTOP RHYTHM — owner, 19.08.2026: "the page shows in full at 100 %
   zoom, without a vertical scrollbar"
   ══════════════════════════════════════════════════════════════════════════
   Measured before a value was changed: the entry sheet was 1049 px tall in a
   1440 x 900 window — 149 px too many. Where those 149 came from is the reason
   every rule below is the one it is, and the reason none of them touches a
   FONT SIZE or a TAP TARGET.

     · 72 px of sheet margin (24 top, 48 bottom)
     · 60 px of header, 26 px of body padding, 24 px of headline and lede margin
     · 58–59 px per field row, eleven of them — and 16 of every row is the
       padding above the label plus the padding under the control

   ⛔ DESKTOP ONLY, AND THAT IS THE WHOLE POINT. The journey is drawn for a phone
   first; a phone has no "fits without scrolling" to aim at and its rhythm is the
   one the delivery drew. Nothing here exists below 1280 px.
   ⛔ AND NOT ONE TAP TARGET SHRINKS. `.jr-gi` keeps its 34 px floor and `.jr-sw`
   stops at 44 — the padding around them is what gives, which is space that was
   never touchable. `.jr-more` keeps its 44 px exactly.
   ⚠️ IT IS A FIT, NOT A GUARANTEE. Five languages set the same form at different
   heights (Arabic runs on Cairo's taller leading), so this buys the German,
   English and Turkish entry a scrollbar-free window and shortens the other two
   without promising them one. Measured per language in the batch report. */
@media (min-width: 1280px) {
  /* ⚠️ 19.08.2026 · THIS `margin-block` IS SUPERSEDED AND KEPT ON PURPOSE. (L3.)
     A later block with the SAME media query — the H3 strip's, near the end of
     this file — sets `.jr-shell { margin-block: 0 auto }`, and equal specificity
     means the last one wins. So this declaration and the `margin-block: 0` in
     the `max-height: 940px` block below never reach a browser.
     ⛔ DOCUMENTED RATHER THAN DELETED, and that is the measured direction on this
     stylesheet: two separate incidents here came from MOVING or REMOVING blocks
     (an orphaned brace swallowed the next rule; a media query left open
     swallowed everything after it), and both were invisible to "the page opens
     and returns 200". The confusion a dead declaration causes is a comment
     problem; the risk of removing it is a customer problem. */
  .jr-shell { margin-block: 12px 16px; }
  .jr-head { padding: 14px 14px 4px; }   /* H3 · the same corner, same rule */
  .jr-body { padding: 0 20px 12px; }
  .jr-h1 { margin-block-end: 4px; font-size: clamp(24px, 3.2vw, 28px); }
  .jr-lede { margin-block-end: 10px; }
  /* the sixteen pixels every row spends above its label and under its control */
  .jr-gl { padding-block-start: 5px; }
  .jr-gi { padding-block-end: 5px; }
  .jr-grp + .jr-grp { margin-top: 10px; }
  .jr-sw { min-height: 44px; padding-block: 6px; }
  .jr-more { margin-top: 8px; }
  .jr-foot { padding: 8px 20px 14px; }
}

/* ⛔ AND IT LIVES AT THE END OF THE FILE ON PURPOSE. Every declaration in it has
   the specificity of the rule it tightens, so order is the only thing that
   decides — placed beside the width rules it belongs to, `.jr-head` two hundred
   lines below simply won and the sheet stayed 1005 px tall. Measured, not
   assumed: the first run of this block moved 44 of the 149 pixels and nothing
   else. A tightening that must be read LAST is written last. */

/* ── and the last twelve pixels, only where they are missing ──────────────
   ⭐ THE BLOCK ABOVE TOOK 1049 px TO 912 IN A 1440 × 900 WINDOW — twelve short.
   Spending those twelve everywhere would take the breathing room off a tall
   desktop that never needed it, so they are spent where the shortfall IS: a
   window under ~940 px of height, which is the laptop class the owner is
   looking at. A 1440 × 1080 screen keeps the roomier rhythm above.
   ⚠️ 22 px RATHER THAN 12, so the fit is not exactly zero: one longer label in
   one language must not put the scrollbar back. */
/* 🔴🔴 AND THE SHEET'S MARGIN BECOMES THE PAGE'S PADDING HERE, WHICH IS THE ONLY
   REASON THE FIT LANDS. `body.jr-page` is `min-height: 100vh` and carries no
   vertical padding or border, so the sheet's block margins COLLAPSE THROUGH it:
   the page was already 900 px tall by declaration and the 8 px of top margin was
   then added on top of that — a document 908 px tall in a 900 px window, with
   the scrollbar bought by a margin that was trying to make room. Measured three
   times before it was believed: shrinking the margin from 28 px to 18 px moved
   the document by 4, not by 10.
   ⇒ The same eighteen pixels, paid by the PAGE, are inside the 100vh. */
@media (min-width: 1280px) and (max-height: 940px) {
  body.jr-page { padding-block: 8px 10px; }
  /* ⚠️ Superseded, like the one above — the H3 block at the end of this file
     sets `margin-block: 0 auto` for every screen from 1280 px. Kept, not
     deleted; see the note there for why this stylesheet does not get tidied. */
  .jr-shell { margin-block: 0; }
  .jr-body { padding-block-end: 6px; }
  .jr-lede { margin-block-end: 8px; }
  .jr-foot { padding: 6px 20px 12px; }
  /* 🔴 ARABIC PAYS 45 OF THESE PIXELS IN LEADING, and only the FORM gives them
     back. `body.jr-page[dir="rtl"] * { line-height: 1.7 }` is a legibility rule
     for Cairo and it stays exactly that for every sentence on the journey — but
     a field LABEL and a field VALUE are one line of UI each, never prose, and at
     1.7 they were adding 3 px per label and 3 px per control across nine rows.
     ⚠️ 1.5 AND NOT THE LATIN 1.35: Cairo's descenders clip below roughly 1.45 at
     these sizes (a recorded defect on this journey), so this takes the slack and
     stops short of the edge. Verified with the clipped-text detector in five
     languages before it was kept. */
  body.jr-page[dir="rtl"] .jr-gl,
  body.jr-page[dir="rtl"] .jr-gl > span,
  body.jr-page[dir="rtl"] .jr-gi { line-height: 1.5; }
}

/* ══════════════════════════════════════════════════════════════════════════
   H2 · THE TICK IS DRAWN HERE, NOT BY THE BROWSER
   ══════════════════════════════════════════════════════════════════════════
   🔴🔴 OWNER, 19.08.2026, WITH A SCREENSHOT: "the checkbox still is not red."
   Every tick on this journey was styled with `accent-color`, which is a REQUEST
   to the browser and not a rule — a user in Windows high-contrast, a forced-
   colors profile or a browser that simply does not honour it gets the platform
   default, and the owner got a black box with a black tick. Nothing in the
   stylesheet was wrong; the stylesheet was asking rather than drawing.
   ⇒ `appearance: none` and the box is ours: our border, our ground, our tick.
   The result is identical in every engine because nothing is left to decide.

   ⚠️ TWO COLOURS, BECAUSE THERE WERE TWO. The journey's own ticks are accent
   red; the readiness list's are the page ink (`.jr-check`), which was a
   deliberate difference and stays one.
   ⛔ AND THE FORCED-COLORS CASE IS ANSWERED RATHER THAN OVERRIDDEN. A user who
   has asked their system for high contrast must keep getting it, so there the
   box uses the SYSTEM's own colours — `Highlight` on `HighlightText` — which is
   the same statement in the vocabulary that user chose. */
.jr-sw input, .jr-check input, .jr-wko input, .jr-check--card input {
  appearance: none; -webkit-appearance: none; margin: 0;
  border: 1.5px solid var(--jr-line-strong); border-radius: 6px;
  background: #fff; cursor: pointer;
  display: inline-grid; place-content: center;
}
.jr-sw input::before, .jr-check input::before,
.jr-wko input::before, .jr-check--card input::before {
  content: ""; width: 11px; height: 11px;
  transform: scale(0); transition: transform .1s ease-out;
  background: #fff;
  /* the tick, as a shape rather than a glyph: no font to load, no baseline to
     fight, and it mirrors nothing because a tick has no direction */
  clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 18%, 84% 0, 40% 68%);
}
.jr-sw input:checked, .jr-check--card input:checked {
  background: var(--jr-accent); border-color: var(--jr-accent);
}
/* ⚖️ OWNER, 24.08.2026, ON THE ZEITEN SCREEN: «يلي بيتم حط الشيك بوكس عليه
   يصير اخضر مو احمر» — an OPEN day is good news, and good news on this journey
   is `--jr-green` (the same word the verify rows and the success window speak).
   ⛔ ONLY the day tick: every other tick keeps the 19.08 accent-red ruling
   ("the checkbox still is not red"), and the forced-colors answer below keeps
   the SYSTEM's own colours for all of them, this one included. */
.jr-wko input:checked { background: var(--jr-green); border-color: var(--jr-green); }
/* ⚖️ The readiness list keeps the page ink it was given — see `.jr-check`. */
.jr-check input:checked { background: var(--jr-ink); border-color: var(--jr-ink); }
.jr-sw input:checked::before, .jr-check input:checked::before,
.jr-wko input:checked::before, .jr-check--card input:checked::before { transform: scale(1); }
/* ⛔ AND THE TICK KEEPS A FOCUS STATE — it is a control, and the owner's "no red
   rectangle" was about the fields somebody types into. A ring on a 20-px box is
   not that rectangle, and a checkbox with no focus state cannot be ticked from a
   keyboard with any confidence. */
.jr-sw input:focus-visible, .jr-check input:focus-visible,
.jr-wko input:focus-visible, .jr-check--card input:focus-visible {
  outline: 2px solid var(--jr-accent); outline-offset: 2px;
}
/* ⚖️ 24.08.2026 · the day tick went green by owner order («خضر كل شي مو بس
   الشيك بوكس») and its ring follows it — the N8 precedent
   (`.jr-cta--done:focus-visible`): a red ring on a green control is the one
   point that does not belong to the statement. AFTER the shared rule, because
   the two selectors weigh the same and the later one wins. */
.jr-wko input:focus-visible { outline-color: var(--jr-green-ink); }
@media (forced-colors: active) {
  .jr-sw input, .jr-check input, .jr-wko input, .jr-check--card input {
    border-color: CanvasText; background: Canvas;
  }
  .jr-sw input:checked, .jr-check input:checked,
  .jr-wko input:checked, .jr-check--card input:checked {
    background: Highlight; border-color: Highlight;
  }
  .jr-sw input::before, .jr-check input::before,
  .jr-wko input::before, .jr-check--card input::before { background: HighlightText; }
}

/* ══════════════════════════════════════════════════════════════════════════
   H2 · THE SHEET SITS IN THE MIDDLE OF THE WINDOW ON A DESKTOP
   ══════════════════════════════════════════════════════════════════════════
   🔴 OWNER, 19.08.2026: "the container in general has to be in the middle of the
   window on desktop." It already was HORIZONTALLY — measured at 0 px of offset
   across six widths in G1 — and the gap he was looking at was underneath it: the
   page is `min-height: 100vh`, so on a window taller than the form all of the
   leftover height fell below the sheet and none above it.

   ⛔ `margin-block: auto`, NEVER `justify-content: center`. Centring a flex line
   distributes NEGATIVE free space as well as positive, so a screen taller than
   the window — `zeiten_dienste`, `review`, every long station — would have had
   its top pushed above the viewport and out of reach, with no scrollbar to bring
   it back. Auto margins are defined to resolve to ZERO when free space is
   negative, so a tall screen keeps its top exactly where it is and only a short
   one centres. That is the whole reason this is a margin and not an alignment.
   ⚠️ AND THE PAGE'S `padding-block` STAYS THE FLOOR: on a window that is only
   just tall enough, the auto margins go to zero and the 8/10 px below survive as
   the gap the sheet must not lose. */
@media (min-width: 1280px) {
  body.jr-page { display: flex; flex-direction: column; }
  /* 🔴🔴 `width: 100%` IS NOT DECORATION HERE — WITHOUT IT THE SHEET COLLAPSES.
     A flex item whose cross-axis margin is `auto` is NOT stretched (the spec
     makes `align-self: stretch` behave as `flex-start` in that case), so the
     moment the page became a flex column the sheet fell back to shrink-to-fit:
     measured at 397–628 px instead of 1120, on every station, in every language.
     Nothing declared a wrong width — the width simply stopped being asked for.
     ⇒ The sheet asks for all of it, `max-width` caps it at the delivery's 1120,
     and the auto inline margins centre what is left. */
  .jr-shell { width: 100%; margin-block: auto; }
}


/* ══════════════════════════════════════════════════════════════════════════
   H3 · THE STRIP ABOVE THE SHEET — TWO ARROWS, THE PATH, THE PHASE
   ══════════════════════════════════════════════════════════════════════════
   🔴🔴 OWNER, 19.08.2026, WITH TWO SCREENSHOTS. The round back arrow lived
   INSIDE the card's header; it now stands above the card, beside a forward
   arrow, the page's own path and the phase this screen belongs to.

   ⛔ IT MUST CARRY THE SHEET'S OWN WIDTH, or it stops being the sheet's strip:
   the same 460 / 820 / 1120 the card takes, granted by the same `--wide` the
   page hands the card, so the leading arrow always stands over the card's
   leading edge — at every size and mirrored in Arabic without a rule.

   ⚠️ AND IT IS WRITTEN AT THE END OF THE FILE ON PURPOSE, like the two blocks
   above it: everything here has the specificity of the rule it tightens, so
   source order is the only thing that decides. (A block placed beside the width
   rules two thousand lines up simply loses.) */
.jr-nav {
  display: flex; align-items: center; gap: 10px;
  width: 100%; max-width: 460px;
  margin-inline: auto;
  /* ⚠️ THE SHEET'S OWN TOP MARGIN, MOVED IN FRONT OF IT. The strip is now the
     first thing on the page, so without this it sat ON the viewport's top edge
     — measured at y = 0 on a 430 px phone. Same expression as `.jr-shell`'s
     block margin, so the two can never drift into two different gaps. */
  margin-block-start: clamp(10px, 2.4vw, 26px);
  margin-block-end: 8px;
  padding-inline: 2px;
}
.jr-nav__pair {
  display: inline-flex; align-items: center; gap: 2px; flex: 0 0 auto;
  padding: 3px;
  border-radius: var(--jr-radius-sm);
  background: var(--jr-card);
  border: 1px solid var(--jr-line);
  box-shadow: var(--jr-shadow-card);
}
.jr-nav__btn {
  /* ⚠️ 34 AND NOT THE 30 THE SCREENSHOT SUGGESTS: with the pair's 3 px of
     padding around it the control is 40 px tall, which is the header arrow's
     old size and the smallest thing this journey asks a thumb to hit. */
  width: 34px; height: 34px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px;
  font-size: 20px; line-height: 1;
  color: var(--jr-ink); text-decoration: none;
}
.jr-nav__btn:hover { background: var(--jr-quiet); }
/* ⛔ THE DEAD ONE IS DEAD ALL THE WAY DOWN: it is a `span` in the markup — no
   href, no tab stop, `aria-hidden` — so this rule only has to make the eye
   agree with what the keyboard and the screen reader already find. */
.jr-nav__btn--off { color: var(--jr-disabled); cursor: default; }
/* ⭐ OW-8 · 31.08.2026 — DER PFEIL, DER DA IST UND NICHT VORWÄRTS GEHT. Er sieht
   aus wie ein Pfeil, weil er einer ist und weil er antwortet; er trägt nur nicht
   die Farbe des Weges. `--jr-hold` ist die Farbe, die diese Reise seit E2 für
   «schau hier hin, nichts ist schiefgegangen» benutzt — dieselbe Bedeutung wie
   der Hinweis, auf den er zeigt. ⛔ Nicht `--off`: das ist ein Zeichen, das man
   nicht drücken kann, und dieses hier kann man. */
.jr-nav__btn--hold { color: var(--jr-amber-ink); }
.jr-nav__where {
  display: flex; flex-direction: column; min-width: 0;
  line-height: 1.2;
}
.jr-nav__path {
  font-size: 12px; font-weight: 500; color: var(--jr-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.jr-nav__name {
  font-size: 15px; font-weight: 700; color: var(--jr-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ⚖️ 24.08.2026 (owner) · the station's glyph, on the name's own line. The row
   exists because `__where` stacks its children — and because the SVG may never
   live INSIDE the data-i18n name (hydration writes textContent and would wipe
   it). 18 px, the brand's dark ink-red, and `currentColor` inside the SVG so a
   theme owns it from one place. Direction-neutral shapes; `gap` is logical. */
.jr-nav__title { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.jr-nav__title > .jr-nav__name { min-width: 0; }
.jr-nav__icon {
  flex: 0 0 auto; display: inline-flex;
  inline-size: 18px; block-size: 18px;
  color: var(--jr-accent-ink);
}
.jr-nav__icon > svg { inline-size: 100%; block-size: 100%; }
@media (min-width: 834px) {
  .jr-nav--wide { max-width: 820px; }
}
@media (min-width: 1280px) {
  .jr-nav--wide { max-width: 1120px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   H3 · ON A TABLET THE SHEET IS THE SCREEN — the owner's second screenshot
   ══════════════════════════════════════════════════════════════════════════
   🔴🔴 OWNER, 19.08.2026, iPad Pro BESIDE AN iPhone: "auf dem iPad muss der
   Container so groß sein wie der Bildschirm … der Abstand ist nur das Padding
   zwischen Containerkante und Bildschirmrand, genau wie auf dem Handy."

   Measured, that is exactly what the delivery's three fixed widths could not
   give him: at 1024 × 1366 the card took the tablet's 820 and left 100 px of
   tinted page on either side and four hundred underneath, while the same card
   on a 430 px phone runs edge to edge behind a 10 px gutter. The gutter is
   already the page's (`padding-inline: clamp(8px, 2.4vw, 24px)` on the body),
   so the tablet band simply stops capping the sheet and lets that one
   expression be the whole frame — 24 px at 1024, the same 10 the phone gets at
   430, and nothing else between the card and the screen.

   ⚖️ 480 px IS WHERE THE CAP FIRST SHOWS. Below it the 460 px maximum is wider
   than the viewport minus its gutter, so the card is already the screen and
   this block would change nothing; above 1279 the desktop keeps the delivery's
   1120 and its centred page, which is what a desktop window is for.

   ⭐ AND THE HEIGHT COMES WITH IT, because "as big as the screen" is not only a
   width: the sheet grows to the bottom of the viewport (`.jr-body` is already
   `flex: 1 1 auto`, so the footer rides down with it) and the page's own
   `padding-block` is the same clamp, which makes the frame even on all four
   sides. The margins are the PAGE's, never the sheet's — a block margin on the
   sheet would collapse straight out through `min-height: 100vh` and buy a
   scrollbar, which is a defect this stylesheet has already paid for once. */
@media (min-width: 480px) and (max-width: 1279px) {
  body.jr-page {
    display: flex; flex-direction: column;
    padding-block: clamp(8px, 2.4vw, 24px);
  }
  /* ⚠️ …and the gap above it is the PAGE's padding here, not the strip's own
     margin — stating both would double the frame at the top and push the sheet's
     bottom edge past the viewport, which is the one thing this band is for. */
  .jr-nav, .jr-nav--wide { max-width: none; margin-block-start: 0; }
  .jr-shell, .jr-shell--wide {
    max-width: none; width: 100%;
    margin-block: 0;
    flex: 1 0 auto;
  }
}

/* ⭐ AND ON THE DESKTOP THE PAIR IS CENTRED, NOT THE CARD ALONE. E3 gave the
   sheet `margin-block: auto` so a window taller than the form would not stack
   all of its free space underneath; with a strip in front of it that same rule
   would have opened the free space BETWEEN the two and left the strip stranded
   at the top. The auto margins therefore move to the OUTSIDE of the pair — top
   of the strip, bottom of the sheet — which keeps E3's property (autos resolve
   to zero when free space is negative, so a tall screen keeps its top exactly
   where it is) and keeps the strip on the card. */
@media (min-width: 1280px) {
  .jr-nav { margin-block-start: auto; }
  .jr-shell { margin-block: 0 auto; }
  /* ⚖️ OWNER, 24.08.2026 (Prüfen screenshot): «بكل المحطات اعمل بادينغ فوق مشان
     ما يبقى هيك العناصر ملزوقة بطرف الصفحة». The `auto` above centres a SHORT
     screen — and resolves to ZERO the moment the content outgrows the window,
     which is every long station (Prüfen measured at y≈0). The guarantee cannot
     live in the auto, so it lives on the page: a floor the centring simply adds
     to. ⛔ The 940-max-height block below keeps overriding this with its own
     measured 6px budget — that laptop's scrollbar-free entry stays paid for. */
  body.jr-page { padding-block-start: 16px; }
}

/* 🔴 H3 · AND THE STRIP PAYS ITS OWN FIFTY PIXELS BACK ON THAT SAME LAPTOP.
   The 1280/940 block far above bought a 1440 x 900 window a scrollbar-free
   German entry with four pixels to spare; a 42 px strip and its 8 px gap spent fifty it did not
   have (measured: document 904 in a 900 px window). The strip is chrome, so the
   pixels come out of the chrome rather than out of the form: a 30 px arrow - the
   size the owner's screenshot actually shows - inside the same 3 px pair, and
   half the gap under it. Measured after: 896. */
@media (min-width: 1280px) and (max-height: 940px) {
  .jr-nav { margin-block-end: 0; }
  .jr-nav__btn { width: 30px; height: 30px; }
  /* 🔴 …AND THE CORNER'S EIGHT PIXELS COME OUT OF THE SAME POCKET. Giving the
     language menu its 14 px of top padding (H3) spent eight on a band that had
     none: the page's own frame and the strip's gap pay four each, and not one
     pixel comes off the form. Measured after: 900 in a 900 px window. */
  body.jr-page { padding-block: 6px 8px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   H3 · THE OPEN LIST OF A <select>, DRAWN BY US WHERE THE BROWSER ALLOWS IT
   ══════════════════════════════════════════════════════════════════════════
   🔴 OWNER, 19.08.2026, WITH A SCREENSHOT OF THE OPEN "Anrede" LIST: the design
   of the dropdown is unacceptable. He is right, and the reason is worth writing
   down once: the CLOSED control has been ours since D3 (`appearance: none`, our
   font, our chevron, our cell), but the OPEN list is not part of the page at
   all — it is an operating-system menu, and no stylesheet has ever been able to
   reach it. That is why the popup came back in the platform's own font with the
   platform's blue selection, in the middle of a sheet that owns every other
   pixel.

   ⭐ SO IT IS ASKED FOR RATHER THAN FORCED — `appearance: base-select`, the
   customizable-select mechanism, inside `@supports`. Where the engine has it
   (Chromium 135+, which is the owner's browser and the majority of this
   funnel's desktop traffic) the list becomes real page content and takes the
   sheet's own radius, border, shadow, type and accent. Where it does not
   (Safari and Firefox today, and every iPhone) NOTHING here applies and the
   platform's own picker stays — which on a phone is the correct control anyway:
   a wheel a thumb can spin, not a menu.

   ⛔ AND NOT ONE LINE OF JAVASCRIPT, WHICH IS THE POINT. The alternative — a
   button plus a `role="listbox"` — is a control that does not exist without a
   script, on a form this funnel deliberately keeps working with scripting off
   (P0.2-B). A `<select>` that a browser draws differently is still a `<select>`:
   same element, same value, same keyboard, same screen reader.

   ⚠️ THE CLOSED CONTROL MUST BE RE-STATED HERE. `appearance: base-select` opts
   the button INTO the UA's base stylesheet, which brings a border, a ground and
   padding of its own — so everything `.jr-gi` and `select.jr-gi` establish is
   said again, or the cell would gain a box on exactly the engines that can draw
   the list well. */
@supports (appearance: base-select) {
  select.jr-gi, select.jr-gi::picker(select) { appearance: base-select; }
  select.jr-gi {
    /* the cell, unchanged — see `.jr-gi` and `select.jr-gi` above */
    width: 100%; box-sizing: border-box;
    min-height: 34px;
    /* logical, like the rule it repeats — the 18 px is the room the chevron
       needs, and it must be on the trailing side in Arabic too */
    padding: 0 0 8px; padding-inline-end: 18px;
    border: 0; border-radius: 4px; background-color: transparent;
    font-family: inherit; font-weight: 500; font-size: 16px; line-height: 1.4;
    color: var(--jr-ink);
    text-align: start;
  }
  /* ⚖️ OUR CHEVRON STAYS, THE UA'S GOES. Ours is already mirrored by hand for
     Arabic four rules up; drawing both would put two arrows in one cell. */
  select.jr-gi::picker-icon { display: none; }

  select.jr-gi::picker(select) {
    /* the sheet's own card, one size down */
    border: 1px solid var(--jr-line);
    border-radius: var(--jr-radius);
    background: var(--jr-card);
    box-shadow: var(--jr-shadow-card);
    padding: 6px;
    margin-block-start: 6px;
    /* ⚠️ never narrower than the cell it belongs to, and never wider than the
       sheet: a country list must not hang over the card's edge on a phone. */
    min-inline-size: anchor-size(width);
    max-inline-size: min(92vw, 420px);
    max-block-size: 320px;
    overflow-y: auto;
  }
  select.jr-gi option {
    display: flex; align-items: center;
    min-height: 44px;              /* a thumb, like every other target here */
    padding: 8px 12px;
    border-radius: 10px;
    font-family: inherit; font-weight: 500; font-size: 16px; line-height: 1.4;
    color: var(--jr-ink);
    background: transparent;
    cursor: pointer;
  }
  /* ⛔ THE TICK GOES AND THE GROUND SAYS IT INSTEAD. The UA marks the current
     option with a checkmark column that indents every row by its width — on a
     three-item salutation list that reads as a stray gap. */
  select.jr-gi option::checkmark { display: none; }
  select.jr-gi option:hover { background: var(--jr-quiet); }
  select.jr-gi option:checked {
    background: var(--jr-accent-soft);
    color: var(--jr-accent-ink);
    font-weight: 600;
  }
  /* the keyboard's own place in the list, in the journey's focus vocabulary */
  select.jr-gi option:focus-visible {
    outline: 2px solid var(--jr-accent);
    outline-offset: -2px;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   19.08.2026 · THE LEGAL LINE ON THE ENTRY SCREEN, AND THE NOTICE STATE
   ═══════════════════════════════════════════════════════════════════════════
   ⚖️ Batch W1 moved the master-data FORM off the advertisement onto
   /3-monate-kostenlos/anmelden/ and left the legal context behind on the page
   that no longer collects anything. § 5 DDG wants the Impressum reachable and
   permanently available on every page of a commercial offering; Art. 13 DSGVO
   wants the processing information AT the moment of collection. Both now sit
   under the form, drawn from the advertisement's own five-language strings.

   ⛔ WRITTEN AT THE END OF THE FILE ON PURPOSE. A block placed beside the rules
   it resembles loses the cascade to anything later with the same specificity —
   measured on this very stylesheet when a block moved next to the width rules
   and reached 44 of 149 elements instead of all of them. */
.jr-legal {
  margin-block-start: 18px;
  padding-block-start: 14px;
  border-block-start: 1px solid var(--jr-hair, rgba(17, 24, 39, .10));
}

.jr-legal__note {
  margin: 0 0 8px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jr-mute);
}

.jr-legal__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
}

/* ⭐ 4.6 : 1 on the sheet ground, above the 4.5 : 1 that AA asks of body text —
   the muted grey these links used to borrow measured 4.14 : 1 and failed it. */
.jr-legal__nav a {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jr-ink-2, #4b5563);
  text-decoration: underline;
  text-underline-offset: 2px;
  /* 44 px of vertical hit area without 44 px of visual weight — the same trick
     the language menu's items use. */
  padding-block: 6px;
}

.jr-legal__nav a:hover,
.jr-legal__nav a:focus-visible {
  color: var(--jr-accent);
}

/* The notice state's fine print — the sentence that says we are deliberately
   showing nothing. `.jr-fine` is the platform's own small-print treatment
   (R2 §B4), reused rather than restyled. */
[data-jr-entry="1"] .jr-fine {
  margin-block-start: 10px;
}

/* ⭐ The notice's only control is a LINK wearing the CTA's clothes, because
   there is deliberately nothing to submit on that screen. */
a.jr-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   19.08.2026 · THE AUDIT'S STYLESHEET REPAIRS (M5 · M8 · M9 · M10 · L1)
   ═══════════════════════════════════════════════════════════════════════════
   ⛔ AT THE END OF THE FILE, like every other late block here: a rule of equal
   specificity placed earlier loses, and this stylesheet has already paid for
   that lesson once. */

/* ── M9 · A FOCUSED FIELD MUST NOT LOSE ITS REFUSAL ─────────────────────────
   `.jr-gc:has(> .jr-gi:focus-visible)` and `.jr-gc--bad` both write `box-shadow`
   on the same element with the same specificity, so the later one won outright:
   the moment the owner touched the field they had got wrong, the red bar that
   said so disappeared. They are different statements — "you are here" and
   "this one is refused" — and both belong on the box at once. */
.jr-gc--bad:has(> .jr-gi:focus-visible) {
  box-shadow: inset 3px 0 0 var(--jr-red), inset 0 -2px 0 var(--jr-accent);
}
[dir="rtl"] .jr-gc--bad:has(> .jr-gi:focus-visible) {
  box-shadow: inset -3px 0 0 var(--jr-red), inset 0 -2px 0 var(--jr-accent);
}
/* The same for a cell carrying an address WARNING, which paints the amber bar. */
.jr-gc--warn:has(> .jr-gi:focus-visible) {
  box-shadow: inset 3px 0 0 var(--jr-amber, #b45309), inset 0 -2px 0 var(--jr-accent);
}
[dir="rtl"] .jr-gc--warn:has(> .jr-gi:focus-visible) {
  box-shadow: inset -3px 0 0 var(--jr-amber, #b45309), inset 0 -2px 0 var(--jr-accent);
}

/* ── M8 · THE SALUTATION CELL CLIPPED ITS OWN DEFAULT VALUE ─────────────────
   `.jr-gc--sal { flex: 0 0 46% }` is 165 px on a 360-px Android viewport, and
   "Ohne Anrede" — the value the field SHIPS WITH — needs more than that at
   15 px. A <select> reports no overflow and no gate can see it; the owner just
   reads a truncated word on the first screen of the journey.
   ⚖️ A floor in pixels rather than a bigger percentage: the row still divides
   proportionally on a wide card, and only stops shrinking where the longest of
   the five languages stops fitting. */
.jr-gc--sal { flex: 0 1 46%; min-width: 190px; }

/* ── M10 · THE LOCATION TEXT IN THE NAV STRIP FAILED AA ─────────────────────
   12 px at 4.14 : 1 on the page ground. WCAG 1.4.3 asks 4.5 : 1 of anything
   under 18.66 px, and this is the line that says WHERE THE VISITOR IS. */
.jr-nav__path { color: var(--jr-ink-2, #4b5563); }

/* ── L1 · THE FLAG'S HAIRLINE RIM NEVER PAINTED ─────────────────────────────
   An `inset` box-shadow on a replaced element (`<img>`) is drawn UNDER the
   image's own content box, so on an opaque flag it is invisible — and three of
   the five flags carry white at the edge, which is exactly the case the rim
   exists for. An outline-style ring sits on top and does not move the layout. */
.jr-langmenu__flag {
  box-shadow: 0 0 0 1px rgba(17, 24, 39, .14);
}

/* ── M5 · viewport-fit=cover WITHOUT A SAFE AREA IS A PROMISE UNKEPT ────────
   The document asks for the full screen on a notched phone and then never reads
   `env(safe-area-inset-*)`, so on an iPhone the sticky footer — which holds the
   ONLY submit button on this screen — sat under the home indicator.
   ⚠️ `max()` so nothing shrinks on a device with no inset. */
.jr-foot {
  padding-block-end: max(var(--jr-foot-pad, 12px), env(safe-area-inset-bottom, 0px));
}
.jr-page {
  padding-inline-start: env(safe-area-inset-left, 0px);
  padding-inline-end: env(safe-area-inset-right, 0px);
}

/* ── 19.08.2026 · CONTRAST ON THE TWO CONTROLS THAT CARRY THE SCREEN ────────
   The brand red `--jr-accent` (#ec3013) gives 4.20 : 1 against white. WCAG 1.4.3
   asks 4.5 : 1 of normal text and 3 : 1 of LARGE text (≥ 18.66 px bold), so the
   two controls fail in different ways and get different answers.

   ⛔ THE BRAND COLOUR IS NOT CHANGED. Which red this platform is belongs to the
   owner, not to an audit; both fixes below stay inside the accessibility rules
   without touching `--jr-accent` for anything else. */

/* The primary action: 17 px bold sits just under the large-text threshold, so it
   was judged as body text. 19 px bold clears it — and on a 371-px phone the
   journey's one button is better for the extra two pixels anyway. */
.jr-cta { font-size: 19px; }

/* „Mehr Angaben" is a 14.5-px text link and can only be answered with ink. This
   is a DARKER SHADE OF THE SAME RED (5.75 : 1), used for small accent text on
   this screen only — the button, the marks and every other accent surface keep
   the brand value. */
.jr-more { color: #c81e16; }

/* ── 19.08.2026 · THE LANGUAGE ITEM WHEN IT IS A BUTTON (audit H8 · L4) ─────
   On the entry form's 422 re-render the menu's items are SUBMIT BUTTONS rather
   than links, so the eighteen typed fields travel with the language change
   instead of being discarded by a GET. A button starts from the UA stylesheet
   — its own border, background, font and centring — so without this reset the
   same list looked like two different controls depending on how you got there.
   ⚠️ `font: inherit` is the one that matters: NO engine inherits font-family
   into a form control, which is the same sentence `.jr-gi` carries for the
   Arabic <select>. */
button.jr-langmenu__item {
  width: 100%;
  border: 0;
  appearance: none;
  cursor: pointer;
  text-align: start;
  font: inherit;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.3;
}
button.jr-langmenu__item[aria-current="true"] { font-weight: 700; }

/* ⚠️ L4 · THE COMMENT ABOVE `.jr-langmenu__list` SAYS "the header is sticky".
   It is not, and has not been since H3 moved the strip above the sheet: the
   journey's header scrolls with the card. The REASON the list floats is still
   sound — a growing header would push the form down under the reader's thumb —
   but the sticky claim is drift, and it is corrected here rather than by editing
   a block whose braces this stylesheet has twice been broken by moving. */

/* ═══════════════════════════════════════════════════════════════════════════
   19.08.2026 · OWNER DECISION 8 — THE LEGAL BLOCK LEAVES THE SHEET
   ═══════════════════════════════════════════════════════════════════════════
   "Ich möchte die rechtlichen Links + die dazugehörige Zeile darüber aus dem
   Hauptcontainer herausnehmen und als eigenen Abschnitt unter den Container
   setzen." — a LAYOUT decision, and the copy is untouched: same two elements,
   same four borrowed strings, same three hrefs, five languages.

   ⛔ WRITTEN AT THE END OF THE FILE, like every block before it. The rules it
   overrides live at line 3361; a copy placed beside them would lose the cascade
   to anything later with equal specificity, which this stylesheet has already
   been measured doing (44 of 149 elements instead of all of them).

   ⭐ WHAT THE MOVE ACTUALLY CHANGES, and why each one is deliberate:

   1. IT NEEDS ITS OWN WIDTH. Inside `.jr-shell` it inherited the sheet's
      max-width; outside it would run the full width of the viewport and the
      links would drift away from the card they belong to. So the three widths
      are repeated from `.jr-shell` / `.jr-shell--wide` — 460 / 820 / 1120 — and
      the 20 px inset is `.jr-body`'s own padding, so the sentence starts on the
      same vertical line the form's labels start on. Repeating three numbers is
      the honest cost of the move; deriving them would mean a shared custom
      property, i.e. touching the sheet's width rules to move a footer.

   2. THE HAIRLINE GOES. `border-block-start` was a DIVIDER INSIDE a card — it
      separated the legal line from the form above it. Outside the card there is
      nothing above it to divide from, and a rule floating on the page ground
      reads as an underline belonging to the sheet. That is precisely the
      mistake the owner corrected on `.jr-foot` on the same day (H1-d: the
      border-top "read as belonging to the content above it" and became a soft
      shadow). The separation is now the gap, which is what separates a section
      from a card everywhere else on this page.

   3. THE SPACE ABOVE IS SMALLER THAN IT LOOKS. `.jr-shell` already carries
      `margin-block: 24px 48px` from 560 px up, so the sheet brings its own 48 px
      of air. 2 px more here, not 18 — the old value was measured against a
      hairline inside a padded card, not against 48 px of page ground.

   🪤 LOGICAL PROPERTIES ONLY. `margin-inline`, `padding-inline`,
   `border-block-start` — this block renders in Arabic on the same page, and a
   `left`/`right` here is a defect that only shows up in one of five languages.
   ═══════════════════════════════════════════════════════════════════════════ */
.jr-legal {
  /* 🔴🔴 THE WIDTH LADDER IS THE SHEET'S, AND IT IS `--wide`'s, NOT `.jr-shell`'s.
     A first version of this block copied `.jr-shell` (460 / 820 / 1120) and was
     WRONG at every size above a phone — measured in a real browser at 794 px:
     the sheet ran the full 756 px of the page while this block sat 460 px wide
     at x=167, a narrow strip floating under a full-width card. Neither the HTML
     gates nor "the page opens" could see it; only a painted box could.

     The ladder that is actually true has THREE states, and the middle one is
     the one that was missed:
       under 480 px   the sheet is capped at 460 and the page gutter frames it
       480 – 1279 px  ⭐ THE SHEET IS THE SCREEN (H3, the owner's iPad note) —
                      `.jr-shell, .jr-shell--wide { max-width: none; width: 100% }`
       1280 px and up the delivery's 1120

     ⭐ AND `.jr-nav` ALREADY SOLVED THIS. The strip above the card is the other
     block that lives OUTSIDE the sheet and has to line up with it, and it uses
     exactly this shape: `width: 100%` with a max-width that the same breakpoints
     move. Copied from it deliberately rather than re-derived — two blocks that
     must agree with a third should be reading the same numbers. */
  width: 100%;
  max-width: 460px;
  margin-block-start: 2px;
  margin-inline: auto;
  /* ⭐ The card's own inner inset (`.jr-body` is `padding: 4px 20px 22px`), so
     the sentence starts on the same vertical line as the form's labels rather
     than on the card's edge. */
  padding-inline: 20px;
  /* ⛔ the divider is gone — see note 2 above */
  padding-block-start: 0;
  border-block-start: 0;
  /* 🔴 20.08.2026 · OWNER, WITH A SCREENSHOT: "more padding from the page edge."
     He was pointing at the BOTTOM, and the sides are not the problem — measured,
     the text sits 180 px in at 1440 px because it is aligned to the sheet's own
     text inset, which is right. What was wrong is underneath:

         1440 × 900   8 px between the last line and the end of the page
          794         19 px
          371         0 px  ← the sentence was touching the edge on a phone

     The page's own `padding-block` is the only thing under this block, and it is
     `clamp(8px, 2.4vw, 24px)` — which is a GUTTER for a card that ends in its
     own 22 px of inner padding, not a footer margin for text that ends at its
     own border. So this block brings its own.

     ⚠️ IT COSTS PAGE HEIGHT, and that is accepted deliberately: it puts ~20 px
     back onto a document that decision 8 already made 42 px taller than the
     viewport at 1440 × 900. Twenty pixels of scroll is cheaper than a legal
     sentence pressed against the bottom of a phone screen — and the block is
     below the fold in both cases either way. */
  padding-block-end: 20px;
}

/* ⭐ THE MIDDLE STATE — the sheet is the screen, so the legal block is too. */
@media (min-width: 480px) and (max-width: 1279px) {
  .jr-legal { max-width: none; }
}

@media (min-width: 1280px) {
  .jr-legal { max-width: 1120px; }
}

/* ── 20.08.2026 · THE LEGAL SECTION IS ONE LINE WHERE THERE IS ROOM ─────────
   ⚖️ OWNER, 20.08: "make the container smaller" — after decision 8 moved this
   block below the sheet, a 1440×900 window scrolls by 56 px where it did not
   before.

   ⛔ AND THE CARD IS NOT WHERE THAT 56 px CAN COME FROM. Measured on the entry
   screen: the WHOLE of its discretionary whitespace is 78 px (head 14/4,
   foot 6/12, body 0/6, h1 4, lede 8, phase 6, group gap 10, disclosure 8) and
   the rows are the delivery's own 55 px. Taking 57 of those 78 would crush
   nearly every gap the owner set by hand on 19.08 — H1-d's soft foot, H3's head
   padding, D3's type scale — to win one window height. F3 forbids a second
   column here, so that route is closed too. The card is left alone.

   ⭐ WHAT IS ACTUALLY OVERSIZED IS THIS BLOCK. Stacked it costs 58 px — a note
   on its own lines and a link row under it — while the sheet beside it is
   820–1120 px wide and mostly empty at that height. Side by side is also the
   ordinary shape for a provider-identification strip.

   📏 MEASURED, AND LESS THAN A FIRST GUESS PROMISED. The German note is 182
   characters, not the ~95 assumed when this was written, so at 808 px it still
   takes TWO lines and the block lands at 44 px rather than one line and 31.
   Arabic is 135 characters and does fit on one line (33 px). The saving is
   therefore 58 ⇒ 44 px (de) / 33 px (ar) — real, and smaller than hoped. The
   number is written here rather than the guess, because the next person to read
   this will be looking for exactly it.

   ⚠️ IT STAYS STACKED BELOW 834 px, where the note alone needs two lines and a
   row would either wrap raggedly or squeeze the links under the reader's thumb.
   Same breakpoint the sheet's own width ladder turns on, so the two never
   disagree about what "wide" means.

   ⛔ THE ORDER IS UNCHANGED IN BOTH SHAPES — note first, links second, exactly
   as the owner named them ("the links + the line above them"). `flex` reorders
   nothing here; it only puts the two on one row. */
@media (min-width: 834px) {
  .jr-legal {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 24px;
  }
  /* The note takes the room the links do not, and may wrap inside it. */
  .jr-legal__note {
    flex: 1 1 24ch;
    margin: 0;
  }
  /* ⛔ `flex: 0 0 auto` — the links never shrink into an ellipsis or wrap one
     word per line; they are the half of this block that § 5 DDG is about. */
  .jr-legal__nav {
    flex: 0 0 auto;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   20.08.2026 · THE DROP ZONE, WHILE A FILE IS OVER IT
   ══════════════════════════════════════════════════════════════════════════
   `.jr-drop` has looked like a drag-and-drop target since P7.2 — a dashed box
   with an upload arrow — and until today nothing listened for a drop, so a
   dragged logo produced no spinner, no message and no logo, because nothing
   had happened. assets/js/jr-logo-shrink.js now accepts the drop; this is the
   half the eye needs, so the box answers BEFORE the file is released.

   ⛔ ONE SCOPED RULE, NO NEW TOKENS. It borrows `:hover`'s own accent border —
   the state is "you may let go here", which is what hover already means on
   this control — and adds only the fill that says the box is armed. Nothing
   outside the logo station carries `.jr-drop`, so the other fifteen screens
   pay nothing.
   ⚠️ WRITTEN AT THE END OF THE FILE on purpose: a block placed mid-file loses
   the cascade to the rules that follow it — recorded on this station. */
.jr-drop.is-dragover {
  border-color: var(--jr-accent);
  border-style: solid;
  background: var(--jr-accent-soft, var(--jr-quiet));
}

/* ══════════════════════════════════════════════════════════════════════════
   21.08.2026 · N1 · THE RECEIPT'S NOTE READS AT THE MEASURE ITS LEDE DOES
   ══════════════════════════════════════════════════════════════════════════
   🔴 MEASURED, NOT ARGUED. G1 granted `gesichert` the sheet, and the note above
   this rule promised that "1120 px of sheet changes where the card sits, not how
   wide the sentence reads". A real browser says otherwise: `.jr-card__text` on
   this screen was drawn as ONE line of 301 px on a phone, 724 px on a tablet and
   **1050 px on a 1440 desktop** — under a lede that `.jr-hail > .jr-lede` holds
   to 332 px. Two paragraphs of the same receipt, one at 40ch and one at three
   times that.

   ⭐ AND THE ANSWER IS THE DELIVERY'S OWN INSTRUCTION, APPLIED ONE ELEMENT OVER.
   `max-width: 40ch` on the lede is the single width instruction the delivery
   wrote for this screen; the card is the sentence directly under it and takes the
   same measure plus room for its own padding and border. `margin-inline: auto`
   keeps the box under the centred column it belongs to.

   📏 MEASURED AFTER, so the number in this comment is the number on the screen:
   the card is **398 px** and its line **368 px** on both the tablet and the 1440
   desktop — one line, in every one of the five languages — against a lede of 332
   (325 in Arabic, where Cairo sets its own measure). ⛔ NOT IDENTICAL TO THE LEDE
   AND NOT MEANT TO BE: `ch` resolves against the element's OWN font size, and the
   card's is not the lede's, so the two land 36 px apart. 368 px of 14-px text is
   about 52 characters — inside the measure a paragraph is read at, which is what
   this rule was for. Forcing the last pixels out of it would mean pinning a px
   width here and losing the delivery's instruction, which is the thing worth
   keeping.

   ⛔ SCOPED TO `.jr-hail >`, so no other `.jr-card` on the journey moves — the
   review's tiles, the waiting screen's phases and the logo's note all keep the
   widths their own screens measured.
   ⚠️ WRITTEN AT THE END OF THE FILE on purpose: a block placed mid-file loses
   the cascade to the rules that follow it — recorded on this platform. */
.jr-hail > .jr-card {
  max-width: calc(40ch + 31px);   /* the lede's measure + 2×14px padding + 2×1.5px border */
  margin-inline: auto;
}

/* ══════════════════════════════════════════════════════════════════════════
   21.08.2026 · N1 · THE RECEIPT'S SENTENCE, ONCE IT CAN HAND OVER THE LINK
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ OWNER, 21.08.2026: "the sentence stays exactly as it is — but pressing it
   copies the link, and a small message says so." So the WORDS do not change and
   the URL is never printed; what changes is that the paragraph becomes pressable.

   ⛔ AND ONLY `.is-copyable` CARRIES ANY OF IT. That class is added by
   assets/js/jr-copy-link.js after it has found a clipboard it can really write
   to, so a browser with scripting off — or without the API — gets the card
   exactly as it was: no pointer, no underline, nothing that offers a press it
   cannot answer. A rule keyed on the markup instead of on the class would put the
   affordance on a screen where the press does nothing.

   ⭐ THE AFFORDANCE IS A DOTTED UNDERLINE, not a button and not a colour change.
   A receipt has one primary action ("Weiter") and the delivery gives it the only
   red on the screen; a second red control here would be two primaries. Dotted is
   the quietest mark that still says "there is something under this" on a phone,
   where there is no hover to discover it with.

   ⭐ AND THE CONFIRMATION BORROWS `--jr-green-ink` — the ink every "this is done"
   on this journey already speaks in (`.jr-vrow--ok`, `.jr-check-row--ok`,
   `.jr-banner--ok`). ⛔ It is NOT a banner and NOT a stripe: this screen already
   carries four success statements on arrival, and a fifth permanent one would be
   the "receipt shouting" F1 removed the green disc to stop. It appears on a press
   and takes itself away again.
   ⚠️ WRITTEN AT THE END OF THE FILE on purpose — a block placed mid-file loses
   the cascade to the rules that follow it. */
.jr-card__text.is-copyable {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-decoration-color: var(--jr-line);
  text-underline-offset: 3px;
}
.jr-card__text.is-copyable:hover {
  text-decoration-color: var(--jr-muted);
}
/* ⭐ The strip's own ring, because a promoted paragraph is a control and every
   other control on this page answers the keyboard the same way. */
.jr-card__text.is-copyable:focus-visible {
  outline: 2px solid var(--jr-accent);
  outline-offset: 2px;
  border-radius: 6px;
}
.jr-card__copied {
  font-family: inherit;
  font-weight: 700;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--jr-green-ink);
  margin: -4px 0 10px;
  opacity: 0;
  transition: opacity 140ms ease-out;
}
.jr-card__copied.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .jr-card__copied { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   21.08.2026 · N-17 · THE LINK GLYPH BESIDE THE RECEIPT'S NOTE
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ OWNER, 21.08.2026: "add it, the way the delivery has it." The artboard's
   `gesichert` note is a row — a 20-px chain, then the sentence and the dated pair
   — and our card had only the second half. No decision ever removed the glyph
   (the green disc above it had one, F1·R1); it was an omission, and it is worth
   closing now that the sentence beside it is the control that copies the link: on
   a phone there is no hover, and a link glyph is what says "there is a link under
   this" before anything is pressed.

   ⭐ THE ROW IS `start`-ALIGNED, not centred, and the glyph does not stretch. The
   note is running text (D7's decision, `.jr-hail > .jr-card { text-align: start }`)
   and the mark belongs on the first line of it, which is what the 2-px nudge is
   for — the same nudge the delivery gives it.
   ⛔ SCOPED TO THIS SCREEN'S CARD. `.jr-card` is drawn by nine other screens; only
   the receipt has a `.jr-card__row` in it, so only the receipt pays for this.
   ⚠️ WRITTEN AT THE END OF THE FILE on purpose — a block placed mid-file loses the
   cascade to the rules that follow it. */
.jr-card__row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.jr-card__glyph {
  flex: 0 0 auto;
  margin-block-start: 2px;
  color: var(--jr-muted);
}
/* ⭐ The column carries the whole note, so the dated pair lines up under the
   sentence rather than under the glyph — the delivery's own split. */
.jr-card__body { min-width: 0; flex: 1 1 auto; }
/* ⛔ …and the sentence's own bottom margin is what separates it from the pair;
   the last thing in the column never adds one, whichever of the two it is. */
.jr-card__body > :last-child { margin-bottom: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   N-12 · WHAT A THUMB HITS, WITHOUT MOVING ONE PAINTED PIXEL   (Batch N2)
   ══════════════════════════════════════════════════════════════════════════
   🔴 MEASURED 21.08.2026 (tools/n2_taps.js, real browser, hit-testing with
   `elementFromPoint` rather than `getBoundingClientRect`): every control of the
   shared journey chrome except the footer button was under the 44 CSS px the
   journey's own visual gate calls "the smallest target a thumb reliably hits" —
   legal links 31, strip arrow 34 (30 on a laptop), language toggle 38, language
   items 42. The footer button was 56.

   ⭐⭐ THE TARGET GROWS, THE INK DOES NOT. Every rule below adds a TRANSPARENT
   `::after` over its control. The painted box, the type, the borders and every
   geometry a delivery board or a visual gate measures stay byte-for-byte what
   they were — which is the only way to close this without re-opening D3, F1, G1
   and H3, all of which settled the sizes of exactly these elements.
   ⚠️ AND THAT IS WHY IT NEEDED ITS OWN TOOL. `getBoundingClientRect()` cannot see
   a pseudo-element, so the older census (n1_gesichert_taps.js) reports 31 px for
   a link that now answers a press across 44. The claim here is about the second
   measurement, and `tools/n2_taps.js` is what makes it.

   ⛔ NO TWO HIT AREAS MAY OVERLAP. A target that reaches into its neighbour
   steals presses, which is worse than the small target it replaced — so every
   expansion below stops at the midpoint of the gap it grows into, and the tool
   fails the run if any two hit boxes intersect.

   ⚠️ WRITTEN AT THE END OF THE FILE, like every block since D3: one placed
   mid-file loses the cascade to the rules that follow it.
   ────────────────────────────────────────────────────────────────────────── */

/* --- the legal row: 31 → 44 tall, and 27 → 45 wide for the shortest of them -
   The column gap is 18 px, so ±9 px makes "AGB" 45 wide and puts its edge
   exactly on its neighbour's — touching, never overlapping.
   ⚠️ AND THE ROW GAP GOES 6 → 14 so the same is true when the three wrap onto
   two lines on a very narrow phone: 6 px of gap against ±6.5 px of reach would
   have been an overlap nobody would see and every thumb would feel. Nothing
   moves at 390 px and above, where the three fit on one line (measured). */
.jr-legal__nav { row-gap: 14px; }
.jr-legal__nav a { position: relative; }
.jr-legal__nav a::after {
  content: '';
  position: absolute;
  inset: -6.5px -9px;
}

/* --- the strip's arrows: 34 (30) → 44, and OUTWARD ONLY ---------------------
   ⛔ THE EXPANSION MUST NOT REACH THE OTHER GLYPH. The two arrows sit 2 px apart
   inside `.jr-nav__pair`, and at most ONE of them is ever a link: the move that
   does not exist is rendered as an `aria-hidden` <span> (H3). A symmetric ±5 px
   would put the live arrow's hit area over the dead one — so a press on the
   greyed-out "back" chevron would navigate FORWARD, which is a worse thing than
   a small target.
   ⇒ Each arrow reaches 1 px into the 2 px gap (the midpoint) and takes the rest
   of its 44 on its own outer side, where the pair's 3 px of padding and the
   strip's own empty space are. Only `a.jr-nav__btn` is styled: the dead span
   gets nothing, because it is not a target.
   ⚖️ AND THE ARROW ITSELF IS UNTOUCHED — 34 px, and 30 on the laptop breakpoint
   H3 sized from the owner's own screenshot. */
a.jr-nav__btn { position: relative; }
a.jr-nav__btn::after { content: ''; position: absolute; }
/* back — the first of the pair, so it grows to the LEADING side */
.jr-nav__pair > a.jr-nav__btn:first-child::after {
  inset-block: -5px;
  inset-inline-start: -9px;
  inset-inline-end: -1px;
}
/* forward — the last of the pair, so it grows to the TRAILING side */
.jr-nav__pair > a.jr-nav__btn:last-child::after {
  inset-block: -5px;
  inset-inline-start: -1px;
  inset-inline-end: -9px;
}

/* --- the language toggle: 38 → 44 ----------------------------------------
   ⚠️ -4 AND NOT -3, MEASURED. A symmetric ±3 answered 42, not 44: the toggle
   sits in a sticky header whose own edge is one pixel inside the reach on each
   side, so the arithmetic that looks right on paper loses two. The number here
   is the one tools/n2_taps.js reads back. */
.jr-langmenu__toggle { position: relative; }
.jr-langmenu__toggle::after {
  content: '';
  position: absolute;
  inset: -4px 0;
}

/* --- the language items: 42 → 44 -----------------------------------------
   The list's own `gap: 2px` is exactly what the two ±1 px take, so the five
   items tile the list without a dead pixel and without an overlap. */
.jr-langmenu__item { position: relative; }
.jr-langmenu__item::after {
  content: '';
  position: absolute;
  inset: -1px 0;
}

/* --- 🔴 AND THE LAPTOP ARROW NEEDS MORE, because it is 30 and not 34 -------
   Same construction, same outward-only direction; only the numbers change so
   that 30 + 1 + 13 = 44 across and 30 + 7 + 7 = 44 down. The breakpoint is
   copied from H3's own rule so the two can never drift apart. */
@media (min-width: 1280px) and (max-height: 940px) {
  .jr-nav__pair > a.jr-nav__btn:first-child::after {
    inset-block: -7px;
    inset-inline-start: -13px;
    inset-inline-end: -1px;
  }
  .jr-nav__pair > a.jr-nav__btn:last-child::after {
    inset-block: -7px;
    inset-inline-start: -1px;
    inset-inline-end: -13px;
  }
}

/* --- N-12 · and the sentence G-2 promoted into a control ------------------
   🔴 MEASURED 21.08.2026: in ARABIC on a desktop the receipt's sentence is ONE
   line — 24 px — where German wraps to two and measures 43. It is a real target
   (`role="button"`, added by jr-copy-link.js), so it answers the same 44 as the
   rest of the chrome.
   ⛔ THE PSEUDO IS SCOPED TO `.is-copyable`, which only exists once the script
   has promoted the paragraph. Without JavaScript the sentence is a sentence and
   nothing on the screen — hit area included — claims otherwise.
   ⚠️ IT REACHES OVER THE DATED PAIR BELOW IT, and that is accepted rather than
   overlooked: the pair is not a control, and the whole card is about the link
   the press copies. The alternative — real padding — would move the card row
   the delivery-fidelity work measured at 338 (de) / 329 (ar). */
.jr-card__text.is-copyable::after {
  content: '';
  position: absolute;
  inset: -10px 0;
}
.jr-card__text.is-copyable { position: relative; }

/* ══════════════════════════════════════════════════════════════════════════
   L-2 · THE LOGO THE OWNER JUST UPLOADED, ON THE SCREEN   (Batch N2)
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ OWNER DECISION 21.08.2026 — after an upload the journey stays on this
   station and the owner sees the STORED file. The card that used to carry only
   the sentence "Logo vorhanden" is now a row: the picture, then the sentence.

   ⭐ THE SAME SHAPE `.jr-card__row` ALREADY DRAWS on the receipt (N-17): a flex
   row, `align-items: center` here rather than `flex-start` because the picture
   is a block and not a first-line mark, and a fixed 72-px box so a wide logo and
   a tall one both leave the sentence on the same line.
   ⛔ `object-fit: contain` AND NOT `cover`. A logo cropped to fill a square is a
   logo with its edges cut off — the same measurement H3 made about the flags,
   with the opposite answer, because there the image WAS the square.
   ⚠️ AND A TRANSPARENT PNG NEEDS SOMETHING BEHIND IT. The whole point of this
   station is a mark with no background; on the card's own white a white-on-
   transparent logo would be an empty box. `--jr-quiet` is the page's own quiet
   ground, which is what every other inset on this journey sits on.

   ⚠️ WRITTEN AT THE END OF THE FILE, like every block since D3.
   ────────────────────────────────────────────────────────────────────────── */
.jr-logo-have {
  display: flex;
  align-items: center;
  gap: 12px;
}
.jr-logo-have__img {
  flex: 0 0 auto;
  width: 72px;
  height: 72px;
  object-fit: contain;
  border-radius: 10px;
  background: var(--jr-quiet);
  padding: 6px;
}
/* 24.08.2026 · the thumbnail is a LINK now (owner: enlarge in a preview
   window). The link wraps the image and nothing else visible — no underline
   box, the image's own radius carries the focus ring, and a hover says
   "this is pressable" without inventing a second control style. */
.jr-logo-have__zoom {
  flex: 0 0 auto;
  display: inline-flex;
  border-radius: 10px;
  cursor: zoom-in;
  text-decoration: none;
}
.jr-logo-have__zoom:hover .jr-logo-have__img { background: var(--jr-line-soft); }
.jr-logo-have__zoom:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 2px; }
/* The sentence takes what is left, and never adds a margin under itself inside
   a row — the same rule `.jr-card__body > :last-child` follows.
   ⭐ R-3 (N7) · `.jr-review__line` joins it: the review tile draws the same
   pairing with its own sentence class, and the rule is about the ROW rather
   than about which screen is drawing it. */
.jr-logo-have > .jr-card__text,
.jr-logo-have > .jr-review__line {
  margin: 0;
  min-width: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   🔴🔴 K-5 · 31.08.2026 · EIGENTÜMER — DER TAUSCH IST JETZT ZU SEHEN
   ⚖️ «اذا المستخدم ولد لوغو بعدين تراجع عن قراراه وقال لأرفع الشعار تبعي!!!!
       … مو مفهوم بشكل واضح للمستخدم عملية التبديل!»

   Wer ein Logo erzeugen ließ und sich dann umentschied, las oben in Grün
   «Dieses Logo wird verwendet» und darunter seine eigene Datei. Der grüne Satz
   wurde in dem Moment falsch, in dem die Datei gewählt war.

   ⭐ ZWEI SÄTZE, EINER SICHTBAR. Der Server schreibt beide (form_logo.php), das
   Stylesheet zeigt den zutreffenden. `.is-swapping` setzt jr-logo-shrink.js auf
   die Karte, sobald eine Datei gewählt ist, und nimmt es zurück, wenn die
   Auswahl aufgehoben wird — eine Klasse, kein Wort.
   ⛔ OHNE SKRIPT ÄNDERT SICH NICHTS, und das ist richtig: ohne Skript gibt es
   auch keine lokale Vorschau, die Datei geht erst mit «Weiter» los, und dann ist
   der grüne Satz bis zum Neuladen wahr.
   ══════════════════════════════════════════════════════════════════════════ */
.jr-logo-have__gone { display: none; }
.jr-logo-have.is-swapping .jr-logo-have__now { display: none; }
.jr-logo-have.is-swapping .jr-logo-have__gone { display: block; }
/* ⚖️ Die Karte hört auf, eine Bestätigung zu sein: kein grüner Rahmen, und das
   Bild tritt zurück, weil es gleich nicht mehr das Logo des Betriebs ist.
   ⛔ Sie wird nicht ausgeblendet — der Betreiber muss sehen, WAS er ersetzt. */
.jr-logo-have.is-swapping {
  border-color: var(--jr-line);
  background: var(--jr-quiet);
}
.jr-logo-have.is-swapping .jr-logo-have__img {
  opacity: .45;
  filter: grayscale(1);
}
@media (prefers-reduced-motion: reduce) {
  .jr-logo-have.is-swapping .jr-logo-have__img { filter: grayscale(1); }
}

/* ══════════════════════════════════════════════════════════════════════════
   L-3 · A PRESS THAT IS STILL TRAVELLING SAYS SO   (Batch N2)
   ══════════════════════════════════════════════════════════════════════════
   🔴 Between the press and the 303 this station said nothing, and the two acts
   behind it are the slowest on the journey: up to 12 MB on a mobile network, and
   17–45 seconds of model time for four proposals. Measured 20.08: the owner
   pressed five times.

   ⭐ THE WORD IS THE SIGNAL; THE MARK IS THE SECOND HALF. `jr-logo-shrink.js`
   swaps the button's word for one the SERVER rendered in the reader's language
   and adds `.is-busy`; this draws a ring turning in front of it.
   ⛔ AND IT IS ONLY EVER ON A BUTTON THE SCRIPT TOUCHED. Without scripting the
   class never appears and this block draws nothing at all.
   ⚠️ `prefers-reduced-motion` STOPS THE TURN, NOT THE MARK: somebody who asked
   for less movement still has to be able to tell that something is happening, so
   the ring stays and simply holds still.
   ⚠️ WRITTEN AT THE END OF THE FILE, like every block since D3.
   ────────────────────────────────────────────────────────────────────────── */
.jr-cta.is-busy {
  cursor: progress;
}
.jr-cta.is-busy::before {
  content: '';
  display: inline-block;
  width: 15px;
  height: 15px;
  margin-inline-end: 9px;
  vertical-align: -2px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: jr-busy-turn .8s linear infinite;
}
@keyframes jr-busy-turn {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .jr-cta.is-busy::before { animation: none; }
}
/* A disabled button must still be readable — the platform's own disabled ink,
   never the browser's grey-on-grey default. */
.jr-cta.is-busy[disabled] {
  opacity: .8;
}

/* ══════════════════════════════════════════════════════════════════════════
   N3 · OWNER, 22.08.2026 — THE QUIET "WEITER", AND THE CARD'S GUTTER
   ══════════════════════════════════════════════════════════════════════════
   > «زر المتابعة بقسم الشعار عند الهوفر الكتابة تصير بيضا و التوهج الأحمر بلاه
   >  و زيد البادينغ تبع الحاوية بشكل عام»

   🔴 THE HOVER WAS A CASCADE ACCIDENT, NOT A DESIGN. `.jr-cta:hover` counts two
   classes and `.jr-cta--ghost` counts one, so on hover the quiet upload button
   took the accent BACKGROUND from the base rule while keeping the ghost's own
   DARK ink — #131936 on #dd2b0f, which measures 3.63:1. A 17px/700 button is
   NOT WCAG "large text" (that starts at 18.66px bold), so the 4.5:1 floor applies
   and it was under it. The white the owner asked for measures 4.74:1 — the owner's taste
   and the floor agree. The background stays the accent: white ink needs a ground.

   🪤 AND THE RED GLOW WAS INHERITED, NEVER DECLARED. `--jr-shadow-cta` is the
   ACCENT button's drop shadow. `.jr-cta--ghost` overrode background, colour and
   border and never reset `box-shadow`, so a white button sat in a red halo in
   its RESTING state — which is the halo in the owner's screenshot. Dropped here
   and not in the base rule: `--ghost` is worn by exactly one button on the whole
   journey — seit 29.08.2026 ist das die erfindende Tuer
   (`.jr-cta--ghost .jr-cta--wand`, unter dem Panel), davor war es der
   Upload-Knopf `.jr-logo-send`. So no other screen pays.
   ⛔ AND THE CLASS STRING DOES NOT MOVE. Die Zusicherungen, die
   `class="jr-cta jr-cta--ghost jr-logo-send"` als ein einziges Literal
   einfroren, sind am 29.08.2026 mit dem Knopf entfallen.
   This is ink, so it is spent in the stylesheet and the markup stays still. */
.jr-cta--ghost { box-shadow: none; }
.jr-cta--ghost:hover {
  background: var(--jr-accent-hover); color: #fff; border-color: var(--jr-accent-hover);
}

/* ── the card's gutter ─────────────────────────────────────────────────────
   ⛔ THE INLINE AXIS ONLY, ON THE BODY AND THE FOOTER ONLY, AND EVERY NUMBER
   BELOW IS THE MEASURED WALL RATHER THAN A TASTE. Three walls were found by
   running `journey_header_language_gate.js` against a first attempt at a
   uniform `clamp(20px, 3.4vw, 28px)`, and all three failed:

   1 · 🔴 THE LOGO STATION'S TWO DOORS. Owner decision §8 (22.08.2026) guarantees
       each door ≥ 334 px at the tablet and ≥ 474 px from 1280 px, with the
       divider lane between them. Every pixel of gutter comes off a door 1:1.
         834 px  · shell 794 (the PAGE gutter binds here, not `max-width`)
                   doors 336.5 at gutter 20  ⇒  2.5 px of room, so 22.
         1280 px+ · shell 1120 (`max-width` binds)
                   doors 480 at gutter 20    ⇒  6 px of room, so 24 keeps two.
   2 · 🪤 THE HEADER IS NOT PART OF THIS. `.jr-head`'s 14 px is frozen by the
       same gate (`edgeGap` must stay 13–15.5) — the language menu's distance to
       the card corner is a stated decision, not a consequence of the body's
       padding. It, `.jr-banner` and `.jr-note` keep their 14 and are untouched.
   3 · ⇒ PHONES KEEP THEIR 20. At 320 px there is nothing to give and the visual
       gate's clipped-text lens is what would collect the bill in German.

   ⚠️ SO THE OWNER GETS +4 px ON THE DESKTOP AND +2 ON THE TABLET, WHICH IS ALL
   THE GEOMETRY HAS. Going further needs a decision, not a stylesheet: either the
   334/474 floor moves, or `.jr-shell--wide` gets wider than D3's 1120. Written
   up in the batch report rather than taken here. */
.jr-shell { --jr-gutter: 20px; }
@media (min-width: 834px)  { .jr-shell { --jr-gutter: 22px; } }
@media (min-width: 1280px) { .jr-shell { --jr-gutter: 24px; } }
.jr-body, .jr-foot { padding-inline: var(--jr-gutter, 20px); }

/* ══════════════════════════════════════════════════════════════════════════
   N3 · THE WAIT, AS A NUMBER AND A SENTENCE (22.08.2026)
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ OWNER: "add an expected time until the model has drawn all the logos, shown
   to the user as a countdown."

   🔴 AND BEFORE THIS BLOCK THE RUNNING SCREEN HAD NO VISIBLE WORD ON IT. The
   sentence that was there sits in `.jr-clip` — a one-pixel box for a screen
   reader — so a sighted owner watched four grey squares for as long as the model
   took, measured at up to 165.7 s. The number needed a home and so did the words.

   ⛔ AT THE END OF THE FILE, LIKE EVERY OTHER BLOCK ADDED TO THIS SHEET. Two
   recorded incidents here came from inserting rules in the middle (an orphaned
   brace swallowed the next rule; a media query left open swallowed the rest).
   ⚠️ NO ANIMATION IS DECLARED HERE ON PURPOSE. A number that changes once a
   second is information, not motion, so `prefers-reduced-motion` has nothing to
   switch off — and the skeleton squares beside it already stop themselves. */
.jr-logo-wait {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin: 0 0 10px;
  font-family: inherit; font-weight: 400; font-size: 14px; line-height: 1.5;
  color: var(--jr-ink);
}
/* 🔴 24.08.2026 · THE N8 LESSON, PAID FOR IN ADVANCE THIS TIME: `display: flex`
   above BEATS the `[hidden]` attribute, and the armed idle block (the countdown
   that waits for the generate press) is delivered hidden. Without this line the
   full expected time would sit visible on a screen where nothing is running. */
.jr-logo-wait[hidden] { display: none; }
/* 🪤 `tabular-nums` AND A FLOOR UNDER THE WIDTH, because this box changes its
   content every second: proportional digits make "1:11" narrower than "1:00"
   and the sentence beside it would twitch left and right for a minute and a
   half. The floor is what "0:00" needs, so nothing reflows at the end either. */
.jr-logo-wait__time {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  min-inline-size: 3.4em;
  font-weight: 700; font-size: 17px; line-height: 1.2;
  color: var(--jr-accent-ink);
}
/* ⛔ The two sentences share one rule and one slot: only one of them is ever
   without `hidden`, and the swap must not change the shape of the line. */
.jr-logo-wait__t { flex: 1 1 auto; min-inline-size: 0; }
.jr-logo-wait__note { margin: 0 0 12px; }

/* ══════════════════════════════════════════════════════════════════════════
   N4 · STATION 4 (zeiten_dienste) — OWNER, 22.08.2026
   ══════════════════════════════════════════════════════════════════════════
   Five points, each one measured against what was on the screen. Written at the
   end of the file for the reason every block here is: two recorded incidents on
   this stylesheet came from inserting rules in the middle. */

/* ── 1 · the offer and the week stop touching ──────────────────────────────
   > "الحاوية التي تحتوي على الأزرار الثلاثة … قريبة جداً من حاوية أوقات الدوام"
   `.jr-block` gives every section 22 px underneath it, which is the rhythm
   BETWEEN peers. These two are not peers: the segmented control asks a question
   and the weeks are its answer, so the eye needs to see the answer start. */
.jr-weeks { margin-block-start: 44px; }

/* ── 2 · one option is active, and it is the checked one ───────────────────
   🔴 MEASURED: `.jr-seg__opt--on` was painted from the STORED plan and never
   moved; `.jr-seg__opt:has(input:checked)` moved with the radio. Both rules were
   live, so choosing "Lieferung" lit TWO options and the owner read it as
   "Abholung stays active". The server class is gone from the markup — this is
   the note that says why the selector below is now the only one.
   ⇒ `.jr-seg__opt--on` keeps its rule at line 1987 for any screen that still
   emits it; nothing on this journey does. */

/* ── 3 · and the week that is offered is the week that is drawn ────────────
   > "عند اختيار Lieferung … يظهر فقط جدول Lieferung"
   ⛔ CSS, NOT A SERVER BRANCH, AND THAT IS THE POINT: the offer is a radio on
   this same screen, so the server cannot know the answer until the form is sent.
   `:has()` lets the sheet follow the radio the moment it is pressed — no script,
   no round trip, and the fallback where `:has()` is unsupported is exactly the
   behaviour this station had yesterday (both weeks drawn).
   ⛔ AND BOTH WEEKS ARE STILL POSTED. Hiding is not deleting: the rules module
   goes on dropping the service nobody offers, so nothing about what is stored
   changes with this rule. */
#jr-form:has(.jr-seg input[value="abholung"]:checked) [data-jr-week="delivery"],
#jr-form:has(.jr-seg input[value="lieferung"]:checked) [data-jr-week="pickup"] {
  display: none;
}

/* ── 4 · "Zweites Zeitfenster" looks like the button it is ─────────────────
   > "يبدو حالياً كنص أكثر من كونه زرّاً"
   It is a `<summary>`: a real control, keyboard-reachable, that opens on its own
   with no script. It was painted as 12 px faint text, which is what a caption
   looks like. ⛔ The ELEMENT does not change — only its ink. */
.jr-wkm__s {
  display: inline-flex; align-items: center;
  margin: 8px 14px; padding: 7px 12px;
  min-height: 34px;
  border: 1.5px solid var(--jr-line); border-radius: 10px;
  background: var(--jr-quiet);
  font-size: 12.5px; font-weight: 600; color: var(--jr-ink);
}
.jr-wkm__s:hover { border-color: var(--jr-line-strong); }
/* ⭐ An open disclosure says so, the way a pressed control does. */
.jr-wkm[open] > .jr-wkm__s { border-color: var(--jr-line-strong); background: var(--jr-card); }

/* ── 4b · 23.08.2026 · OWNER — AN OPEN SECOND WINDOW BELONGS TO THE DAY ABOVE
   > «بمجرد الضغط على اضافة نافذة وقت ثاني لنفس اليوم الخط الفاصل لازم يختفي … و كمان
   >  زر اضافة الوقت يختفي و يظهر بداله زر حذف … خليه فقط ايقونة على نفس بلوك الوقت الثاني»

   Three facts, one state, zero script — `[open]` carries all of it:
     1. the rule that drew a line between the day and its own second window is
        dropped, so the two read as one day;
     2. the word steps aside and the ✕ takes its place;
     3. the ✕ sits in the day row's FOURTH column — the `offen` column — so the
        two time fields line up with the two above them instead of stretching
        into the space the checkbox occupies on the row above.

   🪤 AND `<details>` MAY NOT BE THE GRID — MEASURED, 23.08.2026. The first draft
   made `.jr-wkm[open]` the grid and dissolved the row with `display: contents`,
   so the two inputs would become items of it. The summary landed correctly and
   the inputs did NOT: Chromium wraps everything after `<summary>` in an
   ANONYMOUS block, so `contents` hoisted them into that box instead. The
   computed `grid-column` read 2 and 3 while the boxes sat in column 1 — a
   declaration that agrees with you and a layout that does not. (This is the
   ground `::details-content` was later added to cover.)
   ⇒ THE ROW STAYS THE GRID, which it already was, and simply gains the day's
   fourth column so the two middle columns resolve identically. The ✕ is lifted
   out of flow and set over that column. */
.jr-wkm[open] { border-block-start: 0; position: relative; }
/* ⭐ THE FOURTH COLUMN IS THE DAY'S OWN, MEASURED: `.jr-wko` is a flex box around
   a 20 px checkbox, so the day row resolves to `96px 178px 178px 20px`. Left at
   `auto` this row's fourth column is empty and collapses to nought, and its two
   middle columns each grow by 12 px — which is exactly the drift the owner would
   have seen under the day above. */
.jr-wkm[open] > .jr-wkr--w2 {
  grid-template-columns: clamp(44px, 20%, 96px) minmax(0, 1fr) minmax(0, 1fr) 20px;
  padding-block-end: 7px;
}
/* ⭐ THE ✕ IS THE CHECKBOX'S WIDTH, AND THAT IS MEASURED, NOT CHOSEN. The day
   row's fourth column is `auto` around a 20 px box, so it resolves to 20 px; a
   44 px control here would make this grid's two middle columns 12 px narrower
   EACH and the second window's fields would sit visibly inside the day's. Same
   painted width, same columns, same alignment.
   ⛔ AND IT IS AN ICON, NOT A BUTTON — the owner asked for exactly that
   («خليه فقط ايقونة»), so the frame and the ground the closed state wears are
   dropped here. */
.jr-wkm[open] > .jr-wkm__s {
  position: absolute; inset-inline-end: 14px; top: 50%;
  transform: translateY(-50%);
  margin: 0; padding: 0;
  width: 20px; min-height: 20px;
  justify-content: center;
  border: 0; background: none; border-radius: 6px;
  color: var(--jr-faint);
}
/* ⭐ 44 px of touch WITHOUT a painted pixel moving — N-12's measured solution,
   reused. The overlay is 12 px wider than the icon on each side and the block
   carries 14 px of padding, so it reaches nothing it could overflow. */
.jr-wkm[open] > .jr-wkm__s::after {
  content: ''; position: absolute; top: 50%; inset-inline-start: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.jr-wkm[open] > .jr-wkm__s:hover { color: var(--jr-ink); }
.jr-wkm[open] > .jr-wkm__s:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 3px; }
/* The two faces of the one control. */
.jr-wkm__del { display: none; }
.jr-wkm[open] .jr-wkm__add { display: none; }
.jr-wkm[open] .jr-wkm__del { display: inline-flex; align-items: center; }

/* ── 5 · the delivery prices are their own section ─────────────────────────
   > "ينتهي قسم أوقات الدوام بصرياً، ثم يبدأ قسم Lieferpreise كقسم مستقل وواضح"
   Twenty-two pixels is the distance between two blocks of the same subject. The
   week ends at `z_max` and a different question begins, so the gap says so. */
.jr-prices { margin-block-start: 44px; }

/* ── 6 · "Weitere Postleitzahl", once ──────────────────────────────────────
   > "خيار Weitere Postleitzahl يتكرر مرتين، وهذا غير مطلوب"
   🔴 MEASURED, AND IT IS A PROPERTY OF `<details>`: an opened summary STAYS on
   the screen above its own content. The block nests one disclosure inside the
   next so that each press costs exactly one row — so after one press the screen
   carried the opened summary AND the nested one. Two offers, one act.
   ⇒ An opened one steps aside. The row it revealed is the answer; repeating the
   question above it is what the owner was reading.
   ⛔ AND THIS IS THE NO-SCRIPT PATH. With `jr-plz-rows.js` the disclosures are
   replaced by one button that stays under the last row, up to the owner's fifty. */
details.jr-morerow[open] > summary { display: none; }
.jr-plz-add { margin-top: 12px; }

/* ── 7 · N8 (23.08.2026) · das Erfolgsfenster nach dem Aufbau ──────────────
   ⚖️ BETREIBER: „nach dem Anlegen des Restaurants soll eine Erfolgsmeldung
   kommen, ordentlich gestaltet, grün, als aufklappendes Fenster, mit einem
   einfachen Text zu den nächsten Schritten und einem Knopf: Weiter."

   ⛔⭐⭐ ES IST EIN `<dialog open>`, DAS DER SERVER RENDERT — UND KEIN `showModal()`.
   Ein Fenster, das erst durch JavaScript entsteht, gäbe es für Betreiber ohne
   Skript gar nicht, und zwar auf genau dem Bildschirm, dessen Nachricht „Ihr
   Restaurant existiert" lautet. Deshalb liegt die abgedunkelte Fläche im
   `box-shadow` der Karte selbst (`0 0 0 100vmax`) statt in einem `::backdrop`,
   den nur der Top-Layer bekommt: ein Element, eine Regel, dasselbe Bild mit und
   ohne Skript.
   ⛔ UND `:not([open])` BLEIBT DIE ERSTE ZEILE, wie bei `.jr-logo-dialog`: ohne
   sie zeigt ein Browser ohne `dialog`-Unterstützung den Inhalt einfach an. */
.jr-done:not([open]) { display: none; }

/* 🔴🔴 GEMESSEN AM ARABISCHEN TELEFON, 23.08.2026 — UND DIE ERSTE FASSUNG WAR
   FALSCH. Sie zentrierte mit `inset-inline-start: 50%` plus
   `transform: translate(-50%, -50%)`, und der Kommentar daneben behauptete, das
   sei RTL-sicher. Ist es nicht: im Arabischen bedeutet `inset-inline-start`
   RECHTS, die Verschiebung um −50 % zeigt aber weiterhin nach links — das
   Fenster stand zu neun Zehnteln neben dem Bildschirm. Jede Zusicherung war
   grün: `dir` war `rtl` und die Seite scrollte nicht seitwärts. Sichtbar war es
   nur auf dem Bildschirmfoto.
   ⭐⭐ DIE REPARATUR NIMMT DIE RICHTUNG GANZ AUS DER GLEICHUNG. Der `<dialog>`
   IST jetzt die abgedunkelte Fläche — `inset: 0` auf allen vier Seiten, also
   nichts, was eine Schreibrichtung hätte — und `place-items: center` setzt die
   Karte in die Mitte. Damit fällt auch der `100vmax`-Schatten weg: die Fläche
   hat eine eigene Farbe, weil sie ein eigenes Element ist.
   ⛔ UND DAS BLEIBT OHNE SKRIPT WAHR: nichts hiervon ist `::backdrop`, den nur
   ein per `showModal()` geöffneter Dialog überhaupt bekommt. */
.jr-done {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  inline-size: auto;
  max-inline-size: none;
  block-size: auto;
  max-block-size: none;
  margin: 0;
  padding: 14px;
  overflow: visible;
  border: 0;
  background: rgba(15, 20, 40, .72);
  color: var(--jr-ink);
}

.jr-done__panel {
  position: relative;
  inline-size: min(92vw, 460px);
  max-block-size: 92dvh;
  padding: 26px 22px 22px;
  overflow: auto;
  overscroll-behavior: contain;
  border: 1.5px solid var(--jr-green-line);
  border-radius: 18px;
  background: var(--jr-green-soft);
  text-align: center;
  box-shadow: 0 18px 50px rgba(15, 20, 40, .28);
}

/* ⭐⭐ BAU-1 (24.08.2026) · DAS FENSTER TRÄGT JETZT DAS FERTIGE GEBÄUDE.
   ⚖️ BETREIBER: «وبس يخلص المبنى (مع الرسالة الخضرا) يظهر شكل المبنى مكتمل
   ويكون في زر بالمبنى للدخول الى المطعم يلي تم بناءه.» — Szene 6 der Bau-Szene
   (Abschnitt „station 8“ weiter oben) sitzt in `.jr-done__panel`; ihr einziger
   Knopf ist `.jr-slot-eintreten` in der offenen Tür, und der ist derselbe
   Submit an provision_ack.php, den vorher „Weiter“ unter dem Text auslöste.
   ⛔ Die vier Regeln des N8-Fensters (`__mark`, `__t`, `__s`, `__act`) und
   `.jr-cta--done` sind mit dem Markup gegangen, das sie zeichneten — nichts
   „für alle Fälle“ behalten. Der grüne Kreis mit Haken lebt als Chip der Szene
   weiter (`.jr-bau-fertig`), die Überschrift ist `.jr-bau-titel` (Szene 6), der
   Satz `p_done_s` ist `.jr-bau-sub`. Grün bleibt die Aussage: Boden, Chip,
   Lichter, Girlande; die einzige Akzentfläche ist die Tür. */

/* ⭐⭐ N12 · 27.08.2026 — DIE ZWEI ZUSÄTZLICHEN GRIFFE DERSELBEN TÜR.
   🔬 GEMESSEN: das Fenster hatte genau EINEN Ausgang, den Knopf in der Tür des
   Gebäudes. Das ✕ in der Ecke und der Griff auf die dunkle Fläche — die zwei
   Handgriffe, die jeder Mensch an einem Fenster zuerst versucht — taten nichts,
   und wer sie versuchte, las das Fenster als hängengeblieben.
   ⚖️ ES SIND KEINE ZWEITEN WEGE: beide sind `type="submit" form="jr-bau-enter"`,
   also derselbe POST an provision_ack.php wie der Knopf in der Tür. Eine Tür,
   drei Griffe — und ohne Skript, weil `form="…"` Markup ist.
   ⛔ DIE FLÄCHE LIEGT HINTER DER KARTE (`z-index`), nicht darüber: sie darf
   nichts abfangen, was zur Karte gehört — der aufgezeichnete Fall, in dem ein
   Banner jeden Klick schluckte (Falle 41). */
.jr-done__veil {
  position: absolute;
  inset: 0;
  z-index: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.jr-done__panel { z-index: 1; }
/* ⭐ 44 px Trefferfläche in der Ecke der Karte, richtungsabhängig gesetzt
   (`inset-inline-end`), damit sie auf Arabisch links steht — die Ecke, in der
   dort ein ✕ erwartet wird. */
.jr-done__x {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 6px;
  z-index: 2;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--jr-muted);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.jr-done__x svg { inline-size: 16px; block-size: 16px; }
.jr-done__x:hover, .jr-done__x:focus-visible { color: var(--jr-ink); background: var(--jr-card); }

/* Auf dem Telefon füllt das Fenster die Breite bis auf einen Rand, und die
   Innenabstände geben nach — die Karte muss die Szene und einen 44-px-Knopf
   tragen, ohne dass irgendetwas davon abgeschnitten wird. */
@media (max-width: 420px) {
  .jr-done__panel { inline-size: calc(100vw - 28px); padding: 22px 16px 18px; }
}

/* ── 8 · 24.08.2026 · das Code-Fenster der Kontaktbestätigung ───────────────
   ⚖️ BETREIBER: «لما يكون مطلوب تأكيد الهاتف يظهر بنافذة منفصلة مثل تبع
   الايميل» — solange ein Code unterwegs ist, hebt das Panel die Eingabe in ein
   eigenes Fenster, damit niemand sie in der Seitenspalte suchen muss.

   ⛔⭐ DIE GEOMETRIE IST WÖRTLICH DIE VON `.jr-done` (Abschnitt 7) UND NICHTS
   DAVON WIRD NEU ERFUNDEN: server-gerendertes `<dialog open>`, `:not([open])`
   als erste Zeile, `inset: 0` auf allen vier Seiten plus `place-items: center`
   — die richtungsfreie Mitte, nachdem `inset-inline-start` + `translate(-50%)`
   das N8-Fenster im Arabischen neun Zehntel neben den Bildschirm gestellt
   hatte. Nur die AUSSAGE ist eine andere: kein Erfolg, sondern Arbeit — also
   neutrale Karte statt grüner, und der Knopf bleibt, was er in der Zeile ist. */
.jr-vdialog:not([open]) { display: none; }

.jr-vdialog {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  inline-size: auto;
  max-inline-size: none;
  block-size: auto;
  max-block-size: none;
  margin: 0;
  padding: 14px;
  overflow: visible;
  border: 0;
  background: rgba(15, 20, 40, .72);
  color: var(--jr-ink);
}

.jr-vdialog__panel {
  position: relative;
  inline-size: min(92vw, 460px);
  max-block-size: 92dvh;
  padding: 26px 22px 22px;
  overflow: auto;
  overscroll-behavior: contain;
  border: 1.5px solid var(--jr-line-strong);
  border-radius: 18px;
  background: var(--jr-card);
  text-align: center;
  box-shadow: 0 18px 50px rgba(15, 20, 40, .28);
}

.jr-vdialog__t {
  margin: 0 0 4px;
  font-family: inherit;
  font-weight: 700;
  font-size: 21px;
  line-height: 1.25;
  color: var(--jr-ink);
}

/* Der maskierte Wert — dasselbe LTR-Token wie in der Zeile, nur eine Stufe
   größer: er ist die Antwort auf „welche Nummer?", bevor jemand tippt. */
.jr-vdialog__val {
  margin: 0 0 12px;
  font-family: inherit;
  font-weight: 600;
  font-size: 15px;
  color: var(--jr-muted);
}

.jr-vdialog__say {
  margin: 0 0 14px;
  font-family: inherit;
  font-weight: 400;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--jr-ink);
}

/* Das Fenster zentriert seinen Text; die Wiederkehr-Zeile der Zeile bringt ihre
   eigene Ausrichtung mit und braucht hier nur den Abstand nach unten. */
.jr-vdialog .jr-vrow__again { justify-content: center; margin-block-end: 14px; }

/* Feld und Knopf untereinander, in voller Kartenbreite: ein Code und eine
   Handlung, nichts steht daneben. Das Feld bleibt `.jr-vcode` — Ziffern,
   `dir="ltr"`, `one-time-code` — und erbt nur die Breite neu. */
.jr-vdialog__form { display: grid; gap: 10px; justify-items: stretch; }
.jr-vdialog__form .jr-vcode { inline-size: 100%; text-align: center; font-size: 20px; letter-spacing: 4px; }
.jr-vdialog__form .jr-vbtn { inline-size: 100%; }

/* ⛔ EIN LINK, KEIN SKRIPT-KNOPF: die Abmeldung des Fensters ist eine
   Navigation (`vfx=1`), also sieht sie aus wie eine — leise, unter der
   Handlung, mit echter Trefferfläche. */
.jr-vdialog__close {
  display: inline-block;
  margin-block-start: 14px;
  padding: 8px 14px;
  font-family: inherit;
  font-weight: 600;
  font-size: 14px;
  color: var(--jr-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  border-radius: 8px;
}
.jr-vdialog__close:hover { color: var(--jr-ink); }
.jr-vdialog__close:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 3px; }

@media (max-width: 420px) {
  .jr-vdialog__panel { inline-size: calc(100vw - 28px); padding: 22px 16px 18px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   MU-3 · 30.08.2026 · DIE ZWEI FENSTER DER SPEISEKARTEN-STATION
   ══════════════════════════════════════════════════════════════════════════
   Lieferung: Claude Design, `C:\tmp\design_handoff_upload_flow` (README =
   die Werte, `DialogMehrSpeisekarte.dc.html` · `DialogVerarbeitung.dc.html` ·
   `ProcessScan.dc.html`, je drei Viewports). Hohe Werktreue: Farben, Schrift,
   Abstände, Radien, Schatten und Zeiten stehen so, wie sie geliefert wurden.

   ⛔ OHNE SKRIPT ERSCHEINT KEINES VON BEIDEN (`<dialog>` ohne `open`), und die
   Station ist trotzdem vollständig — deshalb ist die erste Regel `:not([open])`
   und kein `hidden`-Attribut: so verhält es sich genau wie `.jr-done`.

   ⭐ DIE ZWEI FENSTER TEILEN IHRE HÜLLE. Schleier, Karte, Eintritt und der
   Fokusring stehen einmal für beide (`.jr-mu-ask, .jr-mu-go`); nur Inhalt und
   Breite unterscheiden sich (520 px gegen 560 px auf dem Schreibtisch).

   ⚖️ NUR DIE VERWANDLUNG WIRD BEWEGT, die Deckkraft bleibt 1 — die Lieferung
   verlangt es ausdrücklich, damit die Karte auch in einem eingefrorenen Bild
   (Bildschirmfoto, Prüfsonde, `prefers-reduced-motion`) sichtbar ist.
   ⛔ LOGISCH GESCHRIEBEN (inline/block, start/end): Arabisch spiegelt sich von
   selbst. Was eine RICHTUNG meint — der Datenstrom, der Fotoeinzug — wird per
   `[dir="rtl"]` gedreht, in CSS, nie im Markup.
   ═══════════════════════════════════════════════════════════════════════════ */
.jr-mu-ask:not([open]), .jr-mu-go:not([open]) { display: none; }
.jr-mu-ask, .jr-mu-go {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  inline-size: auto; max-inline-size: none;
  block-size: auto; max-block-size: none;
  margin: 0;
  padding: 14px;
  overflow: visible;
  border: 0;
  background: rgba(45, 43, 43, .62);
  color: var(--mu-ink, #201e1d);
}
.jr-mu-ask::backdrop, .jr-mu-go::backdrop { background: rgba(45, 43, 43, .62); }
.jr-mu-ask__panel, .jr-mu-go__panel {
  position: relative;
  display: flex; flex-direction: column;
  inline-size: 100%;
  max-block-size: 92dvh;
  overflow: auto;
  overscroll-behavior: contain;
  border: 0; border-radius: 24px;
  background: #ffffff;
  text-align: start;
  box-shadow: 0 20px 44px rgba(20, 18, 18, .34);
}
.jr-mu-ask__panel { animation: jr-dlg-in .32s cubic-bezier(.2, .8, .25, 1); }
.jr-mu-go__panel { animation: jr-vd-in .42s cubic-bezier(.2, .8, .25, 1); }
@keyframes jr-dlg-in { from { transform: translateY(14px) scale(.98) } to { transform: none } }
@keyframes jr-vd-in { from { transform: translateY(16px) scale(.97) } to { transform: none } }
/* ⭐ EIN RING FÜR ALLES, WAS IN DIESEN FENSTERN FOKUSSIERBAR IST. */
.jr-mu-ask :focus-visible, .jr-mu-go :focus-visible {
  outline: 2px solid var(--jr-accent, #ec3013); outline-offset: 2px;
}

/* ── Fenster 1 · „Haben Sie noch mehr von Ihrer Speisekarte?" ─────────────── */
.jr-mu-ask__body {
  display: flex; flex-direction: column; gap: 14px;
  padding: 22px 18px 0;
}
.jr-mu-ask__head { display: flex; align-items: flex-start; gap: 12px; }
.jr-mu-ask__mark {
  display: grid; place-items: center; flex: none;
  inline-size: 36px; block-size: 36px; border-radius: 999px;
  background: var(--mu-a100, #fff2ef);
}
.jr-mu-ask__mark svg { inline-size: 18px; block-size: 18px; color: var(--jr-accent, #ec3013); }
.jr-mu-ask__headtext { display: flex; flex-direction: column; gap: 7px; min-inline-size: 0; }
.jr-mu-ask__t {
  margin: 0;
  font-family: inherit; font-weight: 600; font-size: 20px; line-height: 1.25;
  letter-spacing: -.02em; color: var(--mu-ink, #201e1d);
}
.jr-mu-ask__have {
  display: flex; align-items: center; gap: 8px;
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.4;
  color: var(--mu-n700, #605d5d);
}
/* 🪤 Die Zahl trägt WEITER `.jr-mu__n` (der Korb spricht sie an) und bekommt
   hier nur ihr rundes Kleid dazu. */
.jr-mu-ask__chip {
  display: inline-grid; place-items: center; flex: none;
  min-inline-size: 26px; block-size: 26px; padding: 0 8px;
  border-radius: 999px;
  background: var(--jr-accent, #ec3013); color: #ffffff;
  font-family: inherit; font-weight: 600; font-size: 13px; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.jr-mu-ask__files { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.jr-mu-ask__file {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--mu-n200, #eae7e7); border-radius: 14px;
}
.jr-mu-ask__ficon {
  display: grid; place-items: center; flex: none;
  inline-size: 34px; block-size: 34px; border-radius: 8px;
  background: var(--mu-n100, #f8f4f4);
}
.jr-mu-ask__ficon svg { inline-size: 17px; block-size: 17px; color: var(--mu-n600, #7d7979); }
.jr-mu-ask__fname {
  flex: 1 1 auto; min-inline-size: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.4;
  color: var(--mu-ink, #201e1d);
}
.jr-mu-ask__fx {
  display: grid; place-items: center; flex: none;
  inline-size: 30px; block-size: 30px; padding: 0;
  border: 0; border-radius: 999px;
  background: transparent; color: var(--mu-n500, #9b9797);
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.jr-mu-ask__fx svg { inline-size: 13px; block-size: 13px; }
.jr-mu-ask__fx:hover { background: var(--mu-a100, #fff2ef); color: var(--jr-accent, #ec3013); }
.jr-mu-ask__tip {
  display: flex; align-items: flex-start; gap: 11px;
  margin: 0;
  padding: 13px 14px;
  border-radius: 14px;
  background: var(--mu-a100, #fff2ef);
}
.jr-mu-ask__tipicon { flex: none; display: block; margin-block-start: 1px; }
.jr-mu-ask__tipicon svg { inline-size: 16px; block-size: 16px; color: var(--jr-accent, #ec3013); }
.jr-mu-ask__tiptext {
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.6;
  color: #2d2b2b;
}
.jr-mu-ask__tipl { font-weight: 600; }
.jr-mu-ask__foot { display: flex; flex-direction: column; gap: 9px; padding: 18px; }
.jr-mu-ask__cta, .jr-mu-ask__quiet {
  display: flex; align-items: center; justify-content: center;
  inline-size: 100%;
  padding: 0 18px;
  border-radius: 999px;
  font-family: inherit; font-weight: 600; line-height: 1.2;
  white-space: nowrap; cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.jr-mu-ask__cta {
  min-block-size: 52px; border: 0;
  background: var(--jr-accent, #ec3013); color: #ffffff; font-size: 15px;
  box-shadow: var(--mu-shadow-sm, 0 1px 2px rgba(45, 43, 43, .14));
}
.jr-mu-ask__cta:hover { background: var(--mu-a600, #dd2b0f); }
.jr-mu-ask__cta:active { background: var(--mu-a700, #ae1800); }
.jr-mu-ask__quiet {
  min-block-size: 50px;
  border: 1px solid var(--mu-n300, #d7d3d3);
  background: #ffffff; color: var(--mu-ink, #201e1d); font-size: 15px;
}
.jr-mu-ask__quiet:hover { background: var(--mu-n100, #f8f4f4); border-color: var(--mu-n400, #bab6b6); }
.jr-mu-ask__cta[disabled], .jr-mu-ask__quiet[disabled] { opacity: .62; cursor: default; }

/* ══ 14.09.2026 · EIGENTÜMER — DAS KAMERABLATT ══════════════════════════════════
   «من الهاتف عم يضغط على زر صور او ارفع - المفروض يفتح كاميرا مو اختيار ملف ! -
    اختيار الملف لازم من داخل الكاميرا»
   Geöffnet nur von jr-menu-camera.js, nur auf einem Telefon — ohne Skript und
   auf dem Desktop gibt es dieses Blatt nie.
   ⛔ Das Bild der Rückkamera wird NIE gespiegelt, auch nicht auf Arabisch: es ist
   ein Foto, kein Text. Die Leiste folgt der Leserichtung (logische Eigenschaften).
   ⛔ `[hidden]` verliert gegen `display` — jede umschaltbare Ansicht hat ihre Wache. */
.jr-mu-cam:not([open]) { display: none; }
.jr-mu-cam {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  inline-size: 100%; max-inline-size: none;
  block-size: 100%; max-block-size: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  background: #0d0c0c;
  color: #ffffff;
}
.jr-mu-cam::backdrop { background: #0d0c0c; }
.jr-mu-cam :focus-visible { outline: 2px solid #ffffff; outline-offset: 3px; }
.jr-mu-cam__stage { position: relative; min-block-size: 0; overflow: hidden; }
.jr-mu-cam__video {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%;
  /* 🔬 `contain`, NOT `cover` (review 14.09.2026): the photo is the WHOLE frame,
     so the preview shows the whole frame — nobody lands in a picture who stood
     outside what the owner saw. */
  object-fit: contain;
  background: #0d0c0c;
  transform: none;
}
.jr-mu-cam__frame { position: absolute; inset: 14% 9%; pointer-events: none; }
.jr-mu-cam__frame span { position: absolute; inline-size: 30px; block-size: 30px; border: 0 solid rgba(255, 255, 255, .92); }
.jr-mu-cam__frame span:nth-child(1) { inset-block-start: 0; inset-inline-start: 0; border-block-start-width: 3px; border-inline-start-width: 3px; border-start-start-radius: 10px; }
.jr-mu-cam__frame span:nth-child(2) { inset-block-start: 0; inset-inline-end: 0; border-block-start-width: 3px; border-inline-end-width: 3px; border-start-end-radius: 10px; }
.jr-mu-cam__frame span:nth-child(3) { inset-block-end: 0; inset-inline-start: 0; border-block-end-width: 3px; border-inline-start-width: 3px; border-end-start-radius: 10px; }
.jr-mu-cam__frame span:nth-child(4) { inset-block-end: 0; inset-inline-end: 0; border-block-end-width: 3px; border-inline-end-width: 3px; border-end-end-radius: 10px; }
.jr-mu-cam[data-jr-menu-cam-state="off"] .jr-mu-cam__frame { display: none; }
.jr-mu-cam__flash { position: absolute; inset: 0; background: #ffffff; opacity: 0; pointer-events: none; }
.jr-mu-cam__flash.is-on { animation: jr-cam-flash .3s ease-out; }
/* 🔬 review 14.09.2026: a softer flash (and the script allows one per 350 ms) —
   a burst of full-white frames is a photosensitivity risk. */
@keyframes jr-cam-flash { from { opacity: .4 } to { opacity: 0 } }
.jr-mu-cam__off:focus-within .jr-mu-cam__app { outline: 2px solid #ffffff; outline-offset: 3px; }
.jr-mu-cam__note {
  position: absolute;
  inset-inline: 16px;
  inset-block-end: 14px;
  margin: 0;
  padding: 9px 14px;
  border-radius: 14px;
  background: rgba(0, 0, 0, .56);
  font-family: inherit; font-weight: 500; font-size: 14px; line-height: 1.5;
  text-align: center;
}
.jr-mu-cam__note[hidden] { display: none; }
.jr-mu-cam__off {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  padding: 24px 22px;
  text-align: center;
}
.jr-mu-cam__off[hidden] { display: none; }
.jr-mu-cam__off-icon { display: block; }
.jr-mu-cam__off-icon svg { inline-size: 42px; block-size: 42px; color: rgba(255, 255, 255, .8); }
.jr-mu-cam__off-t {
  margin: 0; max-inline-size: 34ch;
  font-family: inherit; font-weight: 400; font-size: 15px; line-height: 1.6;
  color: rgba(255, 255, 255, .92);
}
.jr-mu-cam__app {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-block-size: 52px; max-inline-size: 100%;
  padding: 8px 22px;
  border-radius: 999px;
  background: var(--jr-accent, #ec3013); color: #ffffff;
  font-family: inherit; font-weight: 600; font-size: 15px; line-height: 1.3;
  cursor: pointer;
}
.jr-mu-cam__app svg { inline-size: 18px; block-size: 18px; flex: none; }
.jr-mu-cam__x {
  position: absolute;
  inset-block-start: calc(10px + env(safe-area-inset-top, 0px));
  inset-inline-end: 10px;
  z-index: 2;
  display: grid; place-items: center;
  inline-size: 44px; block-size: 44px;
  padding: 0; border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .56); color: #ffffff;
  cursor: pointer;
}
.jr-mu-cam__x svg { inline-size: 14px; block-size: 14px; }
.jr-mu-cam__bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 14px 12px calc(16px + env(safe-area-inset-bottom, 0px));
  background: #0d0c0c;
}
.jr-mu-cam__side {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  min-inline-size: 0; max-inline-size: 100%;
  /* 🔬 12 px, not 4: the counter sits on the icon's corner and stood 4 px OUTSIDE
     the button (mu_camera_probe, 14.09.2026) — now it sits inside its padding. */
  padding: 2px 12px;
  border: 0; background: transparent; color: #ffffff;
  font-family: inherit; font-weight: 600; font-size: 12px; line-height: 1.3;
  text-align: center;
  cursor: pointer;
}
/* 🔬 EACH IN ITS OWN COLUMN, NAMED — with the shutter gone («keine Kamera») an
   unnamed grid pulled «Fertig» into the middle slot (mu_camera_probe, ar 390,
   14.09.2026). */
.jr-mu-cam__files { grid-column: 1; justify-self: start; }
.jr-mu-cam__shot { grid-column: 2; }
.jr-mu-cam__done { grid-column: 3; justify-self: end; }
/* A counter that says 0 over a button that cannot be pressed says nothing. */
.jr-mu-cam__done[disabled] .jr-mu-cam__count { display: none; }
.jr-mu-cam__side[disabled] { opacity: .45; cursor: default; }
.jr-mu-cam__ico {
  position: relative;
  display: grid; place-items: center;
  inline-size: 46px; block-size: 46px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .16);
}
.jr-mu-cam__ico svg { inline-size: 20px; block-size: 20px; }
.jr-mu-cam__done .jr-mu-cam__ico { background: var(--jr-accent, #ec3013); }
.jr-mu-cam__count {
  position: absolute;
  inset-block-start: -6px; inset-inline-end: -8px;
  display: inline-grid; place-items: center;
  min-inline-size: 22px; block-size: 22px; padding: 0 6px;
  border: 2px solid #0d0c0c; border-radius: 999px;
  background: #ffffff; color: #201e1d;
  font-size: 12px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.jr-mu-cam__shot {
  display: grid; place-items: center;
  inline-size: 76px; block-size: 76px;
  padding: 5px;
  border: 4px solid #ffffff; border-radius: 50%;
  background: transparent;
  cursor: pointer;
}
.jr-mu-cam__shot span { display: block; inline-size: 100%; block-size: 100%; border-radius: 50%; background: #ffffff; transition: transform .12s ease; }
.jr-mu-cam__shot:active span { transform: scale(.88); }
.jr-mu-cam__shot[disabled] { opacity: .4; cursor: default; }
.jr-mu-cam__shot[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .jr-mu-cam__flash.is-on { animation: none; }
  .jr-mu-cam__shot span { transition: none; }
}

/* ── Fenster 2 · „Wir tippen Ihre Speisekarte ab" ─────────────────────────── */
/* 🔴 OW-7 · 31.08.2026 · OWNER — «هون الخط الفاصل يلي تحت In Ihre digitale
   Speisekarte eintragen نزله لتحت شوي بشكل منطقي بصرياً».
   Die Null war eine Annahme aus der Zeit, als unter den drei Schritten nichts
   mehr kam: die Trennlinie der Fußzeile lag direkt auf der letzten Zeile, ohne
   den Abstand, den jede andere Kante dieser Karte hat. 18 px ist keine neue
   Zahl — es ist genau der Rand, den dieselbe Regel oben und seitlich schon
   trägt, also sitzt die Linie jetzt dort, wo das Auge sie erwartet. */
.jr-mu-go__body {
  display: flex; flex-direction: column; gap: 15px;
  padding: 18px;
}
.jr-mu-go__kicker {
  display: flex; align-items: center; gap: 8px;
  margin: 0;
  font-family: inherit; font-weight: 600; font-size: 10px; line-height: 1.2;
  letter-spacing: .18em; text-transform: uppercase; color: var(--mu-a700, #ae1800);
}
.jr-mu-go__pulse {
  display: block; flex: none;
  inline-size: 6px; block-size: 6px; border-radius: 999px;
  background: var(--jr-accent, #ec3013);
  animation: jr-vd-dot 1.4s ease-in-out infinite;
}
@keyframes jr-vd-dot { 0%, 100% { opacity: .25 } 50% { opacity: 1 } }
.jr-mu-go__t {
  margin: 0;
  font-family: inherit; font-weight: 600; font-size: 21px; line-height: 1.2;
  letter-spacing: -.02em; color: var(--mu-ink, #201e1d);
}
.jr-mu-go__s {
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.6;
  color: var(--mu-n700, #605d5d);
}
/* ⛔ UNBESTIMMT. Der Streifen startet INNERHALB der Bahn (−30 %), damit auch ein
   stehendes Bild „es läuft" zeigt, und läuft weit hinaus (320 %). */
.jr-mu-go__bar {
  display: block; position: relative;
  inline-size: 100%; block-size: 6px;
  border-radius: 999px; overflow: hidden;
  background: var(--mu-n200, #eae7e7);
}
.jr-mu-go__bar > span {
  display: block; position: absolute; inset-block: 0;
  inline-size: 34%; border-radius: 999px;
  background: var(--jr-accent, #ec3013);
  animation: jr-vd-bar 1.9s cubic-bezier(.5, 0, .5, 1) infinite;
}
@keyframes jr-vd-bar { from { transform: translateX(-30%) } to { transform: translateX(320%) } }
[dir="rtl"] .jr-mu-go__bar > span { animation-name: jr-vd-bar-rtl; }
@keyframes jr-vd-bar-rtl { from { transform: translateX(30%) } to { transform: translateX(-320%) } }
.jr-mu-go__steps { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
.jr-mu-go__step {
  display: flex; align-items: center; gap: 10px;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.4;
  color: var(--mu-n600, #7d7979);
}
.jr-mu-go__mark {
  display: grid; place-items: center; flex: none;
  inline-size: 20px; block-size: 20px; border-radius: 999px;
  border: 1.5px solid var(--mu-n300, #d7d3d3);
}
.jr-mu-go__step--done { color: var(--mu-n700, #605d5d); }
.jr-mu-go__step--done .jr-mu-go__mark {
  border-color: transparent; background: var(--jr-accent, #ec3013); color: #ffffff;
}
.jr-mu-go__step--done .jr-mu-go__mark svg { inline-size: 11px; block-size: 11px; }
.jr-mu-go__step--now { font-weight: 600; color: var(--mu-ink, #201e1d); }
.jr-mu-go__step--now .jr-mu-go__mark {
  border-color: transparent;
  background: var(--mu-a100, #fff2ef);
  animation: jr-vd-step 1.6s ease-in-out infinite;
}
@keyframes jr-vd-step { 0%, 100% { background-color: #fff2ef } 50% { background-color: #ffe0d9 } }
.jr-mu-go__inner {
  display: block; inline-size: 6px; block-size: 6px; border-radius: 999px;
  background: var(--jr-accent, #ec3013);
}
.jr-mu-go__foot {
  display: flex; flex-direction: column; gap: 12px;
  padding: 14px 18px 18px;
  border-block-start: 1px solid var(--mu-n200, #eae7e7);
}
.jr-mu-go__note {
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.5;
  color: var(--mu-n600, #7d7979);
}
.jr-mu-go__bg {
  display: flex; align-items: center; justify-content: center;
  inline-size: 100%; min-block-size: 48px; padding: 0 20px;
  border: 1px solid var(--mu-n300, #d7d3d3); border-radius: 999px;
  background: #ffffff; color: var(--mu-ink, #201e1d);
  font-family: inherit; font-weight: 600; font-size: 14px; line-height: 1.2;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.jr-mu-go__bg:hover { background: var(--mu-n100, #f8f4f4); border-color: var(--mu-n400, #bab6b6); }

/* ── ProcessScan · Fotostapel → KI → Datenstrom → digitale Karte ──────────── */
.jr-pr {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  inline-size: 100%; block-size: 146px;
  padding: 0 16px;
  border-radius: 18px; overflow: hidden;
  background: linear-gradient(180deg, #f8f4f4, #eae7e7);
}
.jr-pr__g { position: relative; display: flex; flex-direction: column; align-items: center; gap: 7px; flex: none; }
.jr-pr__cap {
  display: block;
  font-family: inherit; font-weight: 600; font-size: 9px; line-height: 1;
  letter-spacing: .1em; text-transform: uppercase; color: var(--mu-n600, #7d7979);
}
/* 1 · der Stapel, aus dem ein Blatt eingezogen wird */
.jr-pr__g--stack { inline-size: 56px; }
.jr-pr__stack { position: relative; display: block; inline-size: 56px; block-size: 100px; }
[dir="rtl"] .jr-pr__stack { transform: scaleX(-1); }
.jr-pr__sheet {
  position: absolute; inset-block-start: 20px; inset-inline-start: 6px;
  display: block; inline-size: 44px; block-size: 60px;
  border-radius: 6px; background: #ffffff;
  box-shadow: 0 1px 3px rgba(45, 43, 43, .16);
}
.jr-pr__sheet--b1 { transform: rotate(6deg); }
.jr-pr__sheet--b2 { transform: rotate(-6deg); }
.jr-pr__sheet--b2 > span, .jr-pr__sheet--top > span {
  position: absolute; inset-inline-start: 7px; display: block;
  block-size: 3px; border-radius: 2px; background: var(--mu-n300, #d7d3d3);
}
.jr-pr__sheet--b2 > span:nth-child(1), .jr-pr__sheet--top > span:nth-child(1) { inset-block-start: 10px; inline-size: 22px; background: var(--jr-accent, #ec3013); }
.jr-pr__sheet--b2 > span:nth-child(2), .jr-pr__sheet--top > span:nth-child(2) { inset-block-start: 20px; inline-size: 30px; }
.jr-pr__sheet--b2 > span:nth-child(3), .jr-pr__sheet--top > span:nth-child(3) { inset-block-start: 28px; inline-size: 26px; }
.jr-pr__sheet--top { animation: jr-pr-feed 4.2s cubic-bezier(.45, 0, .35, 1) infinite; }
@keyframes jr-pr-feed {
  0% { transform: translateX(0) rotate(-4deg); opacity: 1 }
  62% { transform: translateX(34px) scale(.93) rotate(-4deg); opacity: 1 }
  80%, 100% { transform: translateX(34px) scale(.93) rotate(-4deg); opacity: 0 }
}
/* 2 · die Erkennung — der Streifen zieht HINTER dieser Karte durch */
.jr-pr__g--ai { z-index: 2; }
.jr-pr__card {
  position: relative; display: block;
  inline-size: 70px; block-size: 104px;
  border-radius: 12px; overflow: hidden;
  background: #ffffff;
  box-shadow: var(--mu-shadow-md, 0 3px 10px rgba(45, 43, 43, .16));
}
.jr-pr__beam {
  position: absolute; inset-inline: 0; inset-block-start: 0;
  display: block; block-size: 2px;
  background: var(--jr-accent, #ec3013);
  box-shadow: 0 0 10px 2px rgba(236, 48, 19, .55);
  animation: jr-pr-beam 2.1s cubic-bezier(.4, 0, .3, 1) infinite;
}
@keyframes jr-pr-beam { 0% { transform: translateY(0); opacity: 0 } 8% { opacity: 1 } 88% { opacity: 1 } 100% { transform: translateY(74px); opacity: 0 } }
.jr-pr__ocr {
  position: absolute; inset-inline-start: 9px;
  display: block; block-size: 11px;
  border: 1.5px solid var(--mu-n300, #d7d3d3); border-radius: 3px;
  animation: jr-pr-ocr 2.1s linear infinite;
}
.jr-pr__ocr:nth-of-type(1) { inset-block-start: 12px; inline-size: 40px; animation-delay: 0s; }
.jr-pr__ocr:nth-of-type(2) { inset-block-start: 29px; inline-size: 52px; animation-delay: .45s; }
.jr-pr__ocr:nth-of-type(3) { inset-block-start: 46px; inline-size: 34px; animation-delay: .9s; }
.jr-pr__ocr:nth-of-type(4) { inset-block-start: 63px; inline-size: 46px; animation-delay: 1.35s; }
@keyframes jr-pr-ocr {
  0%, 14% { border-color: #d7d3d3; background: transparent }
  20%, 40% { border-color: #ec3013; background: #fff2ef }
  56%, 100% { border-color: #d7d3d3; background: transparent }
}
.jr-pr__ai {
  position: absolute; inset-block-end: 6px; inset-inline: 6px;
  display: flex; align-items: center; gap: 3px;
}
.jr-pr__ai svg { flex: none; inline-size: 12px; block-size: 12px; color: var(--jr-accent, #ec3013); }
.jr-pr__cap--in { font-size: 9px; letter-spacing: .06em; }
/* 3 · der Datenstrom */
.jr-pr__g--flow { flex: 0 1 104px; min-inline-size: 44px; align-self: center; block-size: 14px; }
/* ⚖️⚖️ 31.08.2026 · EIGENTÜMER — «خطّ نقل البيانات لازم يكون من الورق للجهاز،
   مو من خلف الجهاز». HIER STAND `transform: scaleX(-1)`, UND ES IST FORT.
   Die Spiegelung war nötig, solange die Marken mit einem PHYSISCHEN
   `translateX(86px)` liefen — physisch heisst immer nach rechts, also musste im
   Arabischen die ganze Gruppe umgedreht werden. Die Bahn läuft jetzt über
   `inset-inline-start` (siehe @keyframes jr-pr-token), und das ist von sich aus
   schreibrichtungs-treu: sie beginnt an der Anfangskante und endet an der
   Endkante, in beiden Richtungen.
   ⛔ EINE ZWEITE SPIEGELUNG WÄRE JETZT EIN FEHLER: sie würde die Marken im
   Arabischen wieder VOM Telefon WEG laufen lassen — genau die Beschwerde, in
   der anderen Sprache. */
.jr-pr__rail {
  position: absolute; inset-inline: 0; inset-block-start: 6px;
  display: block; block-size: 2px; border-radius: 999px;
  background: var(--mu-n300, #d7d3d3);
  animation: jr-pr-pulse 2.4s ease-in-out infinite;
}
@keyframes jr-pr-pulse { 0%, 100% { opacity: .5 } 50% { opacity: 1 } }
.jr-pr__tok {
  position: absolute; inset-block-start: 0; inset-inline-start: 0;
  display: grid; place-items: center;
  inline-size: 18px; block-size: 14px; border-radius: 999px;
  animation: jr-pr-token 2.4s cubic-bezier(.45, 0, .4, 1) infinite;
}
.jr-pr__tok > span { display: block; inline-size: 8px; block-size: 2px; border-radius: 999px; background: #ffffff; }
.jr-pr__tok--1 { background: var(--jr-accent, #ec3013); animation-delay: 0s; }
.jr-pr__tok--2 { background: var(--mu-a500, #ff563c); animation-delay: .8s; }
.jr-pr__tok--3 { background: #ff9783; animation-delay: 1.6s; }
/* ⚖️⚖️🔴 31.08.2026 · EIGENTÜMER — «خطّ نقل البيانات لازم يكون من الورق للجهاز،
   مو من خلف الجهاز» ─────────────────────────────────────────────────────────
   🔬 IN CHROMIUM GEMESSEN, BEVOR EINE ZEILE GEÄNDERT WURDE (390 · 834 · 1440,
   ltr und rtl), weil die Bilder des Eigentümers zweimal zu gross ankamen:

     Breite   Bahn (.jr-pr__g--flow)   Weg der Marke   Ende gegenüber dem Telefon
     390 px          68 px                 86 px        26 px DAHINTER   ⟵ der Fehler
     834 px         104 px                 86 px        10 px davor      ok
     1440 px        104 px                 86 px        10 px davor      ok

   ⇒ DER WEG WAR EINE FESTE ZAHL, DIE BAHN NICHT. `.jr-pr__g--flow` ist
   `flex: 0 1 104px` mit `min-inline-size: 44px`, schrumpft auf dem Telefon also
   auf 68 px — die Marke lief trotzdem ihre vollen 86 px und verschwand
   26 px WEIT UNTER dem Telefon. Auf dem Gerät des Eigentümers sah es damit aus,
   als käme der Strom NICHT vom Papier, sondern von hinter dem Gerät hervor.
   ⛔ Es war nie die Richtung. Die Richtung war immer richtig — es war die LÄNGE.

   ⭐ DIE ZAHL IST JETZT DIE BAHN SELBST. `inset-inline-start` misst sich am
   umgebenden Block, also an `.jr-pr__g--flow`: die Marke startet an dessen
   Anfangskante und hält an dessen Endkante, welche Breite die Bahn auch hat.
   `- 18px` ist die Breite der Marke, damit sie mit ihrer VORDERKANTE ankommt
   und nicht mit ihrer Mitte darüber hinausschiesst.
   ⛔ UND DESHALB NICHT MEHR `transform`: `translateX(%)` rechnet gegen die
   EIGENE Breite der Marke (18 px), nicht gegen die Bahn — es kann diese Frage
   also gar nicht beantworten. Der Preis ist Layout statt Compositing für drei
   absolut gesetzte 18-px-Elemente in einem Fenster, das ohnehin offen wartet;
   ⭐ der Gewinn ist eine Zeichnung, die auf JEDER Breite dasselbe sagt.
   ⛔ Und weil `inset-inline-start` logisch ist, entfällt die RTL-Spiegelung
   oben — siehe dort. */
@keyframes jr-pr-token {
  0% { inset-inline-start: 0; opacity: 0 }
  10% { opacity: 1 }
  90% { opacity: 1 }
  100% { inset-inline-start: calc(100% - 18px); opacity: 0 }
}
/* 4 · die digitale Karte, die sich füllt */
.jr-pr__g--phone { inline-size: 66px; }
.jr-pr__phone {
  position: relative; display: block;
  inline-size: 66px; block-size: 104px;
  border: 2px solid var(--mu-ink, #201e1d); border-radius: 12px;
  background: #ffffff; overflow: hidden;
}
.jr-pr__ear {
  position: absolute; inset-block-start: 5px; inset-inline-start: 50%;
  display: block; inline-size: 18px; block-size: 3px; margin-inline-start: -9px;
  border-radius: 999px; background: var(--mu-n300, #d7d3d3);
}
.jr-pr__screen { position: absolute; inset-block: 14px 10px; inset-inline: 6px; display: block; overflow: hidden; }
.jr-pr__roll { display: flex; flex-direction: column; gap: 4px; animation: jr-pr-scroll 5.6s linear infinite; }
@keyframes jr-pr-scroll { from { transform: translateY(0) } to { transform: translateY(-46px) } }
.jr-pr__cat { display: block; inline-size: 26px; block-size: 4px; border-radius: 2px; background: var(--jr-accent, #ec3013); }
.jr-pr__dish { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.jr-pr__dish > span { display: block; flex: 1 1 auto; block-size: 3px; border-radius: 2px; background: var(--mu-n400, #bab6b6); }
.jr-pr__dish > b { display: block; flex: none; inline-size: 12px; block-size: 5px; border-radius: 2px; background: var(--mu-a200, #ffe0d9); }
.jr-pr__fade {
  position: absolute; inset-inline: 0; inset-block-end: 0;
  display: block; block-size: 14px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0), #ffffff);
}
.jr-pr__home {
  position: absolute; inset-block-end: 4px; inset-inline-start: 50%;
  display: block; inline-size: 20px; block-size: 2px; margin-inline-start: -10px;
  border-radius: 999px; background: var(--mu-n300, #d7d3d3);
}

/* ── Tablet ab 834 px ──────────────────────────────────────────────────────── */
@media (min-width: 834px) {
  .jr-mu-ask, .jr-mu-go { padding: 32px; }
  .jr-mu-ask__panel, .jr-mu-go__panel { box-shadow: 0 24px 52px rgba(20, 18, 18, .32); }
  .jr-mu-ask__panel { inline-size: 480px; }
  .jr-mu-go__panel { inline-size: 500px; }
  .jr-mu-ask__body { gap: 16px; padding: 28px 28px 0; }
  .jr-mu-ask__head { gap: 14px; }
  .jr-mu-ask__mark { inline-size: 40px; block-size: 40px; }
  .jr-mu-ask__mark svg { inline-size: 20px; block-size: 20px; }
  .jr-mu-ask__t { font-size: 23px; }
  .jr-mu-ask__have { font-size: 13.5px; }
  .jr-mu-ask__chip { min-inline-size: 28px; block-size: 28px; padding: 0 9px; font-size: 14px; }
  .jr-mu-ask__file { gap: 11px; padding: 9px 11px; }
  .jr-mu-ask__ficon { inline-size: 36px; block-size: 36px; border-radius: 9px; }
  .jr-mu-ask__fname { font-size: 13.5px; }
  .jr-mu-ask__tip { gap: 12px; padding: 14px 16px; }
  .jr-mu-ask__tipicon svg { inline-size: 17px; block-size: 17px; }
  .jr-mu-ask__tiptext { font-size: 13.5px; }
  .jr-mu-ask__foot { padding: 20px 28px 24px; }
  .jr-mu-ask__cta { min-block-size: 52px; }
  .jr-mu-ask__quiet { min-block-size: 48px; font-size: 14.5px; }
  .jr-mu-go__body { gap: 18px; padding: 26px 28px; }
  .jr-mu-go__kicker { font-size: 10.5px; }
  .jr-mu-go__pulse { inline-size: 7px; block-size: 7px; }
  .jr-mu-go__t { font-size: 24px; }
  .jr-mu-go__s { font-size: 14px; }
  .jr-mu-go__bar > span { inline-size: 32%; }
  .jr-mu-go__step { font-size: 13.5px; }
  .jr-mu-go__foot { padding: 16px 28px 20px; }
  .jr-mu-go__note { font-size: 12.5px; }
  .jr-mu-go__bg { min-block-size: 46px; }
}

/* ── Schreibtisch ab 1280 px ───────────────────────────────────────────────── */
@media (min-width: 1280px) {
  .jr-mu-ask, .jr-mu-go { padding: 40px; }
  .jr-mu-ask__panel, .jr-mu-go__panel { border-radius: 26px; box-shadow: 0 28px 60px rgba(20, 18, 18, .34); }
  .jr-mu-ask__panel { inline-size: 520px; }
  .jr-mu-go__panel { inline-size: 560px; }
  .jr-mu-ask__body { gap: 18px; padding: 32px 34px 0; }
  .jr-mu-ask__head { gap: 16px; }
  .jr-mu-ask__mark { inline-size: 44px; block-size: 44px; }
  .jr-mu-ask__mark svg { inline-size: 22px; block-size: 22px; }
  .jr-mu-ask__t { font-size: 26px; line-height: 1.2; letter-spacing: -.015em; }
  .jr-mu-ask__have { font-size: 14px; }
  /* ⭐ Der Chip springt einmal auf, wenn das Fenster kommt — die Zahl ist die
     einzige Angabe darin, die sich von Schwung zu Schwung ändert. */
  .jr-mu-ask__chip {
    min-inline-size: 30px; block-size: 30px; padding: 0 10px; font-size: 15px;
    animation: jr-dlg-count .5s cubic-bezier(.2, .9, .3, 1) .18s both;
  }
  @keyframes jr-dlg-count { 0% { transform: scale(.6) } 62% { transform: scale(1.08) } 100% { transform: scale(1) } }
  .jr-mu-ask__file { gap: 12px; padding: 10px 12px; border-radius: 16px; }
  .jr-mu-ask__ficon { inline-size: 40px; block-size: 40px; border-radius: 10px; }
  .jr-mu-ask__ficon svg { inline-size: 19px; block-size: 19px; }
  .jr-mu-ask__fname { font-size: 14px; }
  .jr-mu-ask__fx { inline-size: 32px; block-size: 32px; }
  .jr-mu-ask__tip { gap: 13px; padding: 16px 18px; border-radius: 16px; }
  .jr-mu-ask__tipicon svg { inline-size: 18px; block-size: 18px; }
  .jr-mu-ask__tiptext { font-size: 14px; }
  .jr-mu-ask__foot { gap: 10px; padding: 22px 34px 26px; }
  .jr-mu-ask__cta { min-block-size: 54px; font-size: 16px; }
  .jr-mu-ask__quiet { min-block-size: 50px; font-size: 15px; }
  /* 🔴🔴 OW-5 · 31.08.2026 — DIE TRENNLINIE KLEBTE AM LETZTEN SCHRITT.
     ⚖️ EIGENTÜMER, zum ZWEITEN Mal gemeldet: «السطر الفاصل بهي النافذة تحت جملة
     ‹ندخلها في قائمة طعامك الرقميّة› نزله شوي بحيث يبعد عن النص» — und danach:
     «بلا الطمع و عطو المستخدمين حقهم».
     🪤 DIE URSACHE STAND NUR IN DIESER EINEN BREITE: `padding: 30px 34px 0` —
     die NULL unten. Der Rumpf endete exakt an der Textunterkante, und
     `.jr-mu-go__foot` setzt sein `border-block-start` unmittelbar dort an. Auf
     Telefon (18px) und Tablet (26px) war der Abstand immer da, deshalb blieb es
     bei einer Sichtprüfung am kleinen Viewport unsichtbar.
     ⛔ ES IST KEIN MARGIN AM LETZTEN LISTENPUNKT. Der Abstand gehört dem Rumpf,
     wie oben und seitlich auch — ein Margin an der Liste wäre eine zweite Stelle,
     an der derselbe Rand gepflegt werden müsste, und würde beim nächsten Element
     unter der Liste (dem `--stuck`-Kasten) wieder fehlen. */
  .jr-mu-go__body { gap: 20px; padding: 30px 34px 28px; }
  .jr-mu-go__kicker { font-size: 11px; }
  .jr-mu-go__t { font-size: 27px; letter-spacing: -.015em; }
  .jr-mu-go__s { font-size: 15px; }
  .jr-mu-go__step { font-size: 14px; }
  .jr-mu-go__mark { inline-size: 22px; block-size: 22px; }
  .jr-mu-go__step--done .jr-mu-go__mark svg { inline-size: 12px; block-size: 12px; }
  .jr-mu-go__inner { inline-size: 7px; block-size: 7px; }
  .jr-mu-go__foot { flex-direction: row; align-items: center; justify-content: space-between; gap: 20px; padding: 18px 34px 22px; }
  .jr-mu-go__note { flex: 1 1 auto; font-size: 13px; }
  .jr-mu-go__bg { inline-size: auto; flex: none; min-block-size: 46px; font-size: 14.5px; }
}

/* ⭐ Bewegung ist Dekoration: jede Schleife hält auf ihrem ersten Bild, und alle
   vier Gruppen des Bildes bleiben dort lesbar (Lieferung, „Motion contract"). */
@media (prefers-reduced-motion: reduce) {
  .jr-mu-ask__panel, .jr-mu-go__panel, .jr-mu-ask__chip,
  .jr-mu-go__pulse, .jr-mu-go__bar > span, .jr-mu-go__step--now .jr-mu-go__mark,
  .jr-pr__sheet--top, .jr-pr__beam, .jr-pr__ocr, .jr-pr__rail, .jr-pr__tok, .jr-pr__roll {
    animation: none !important;
  }
  /* ⛔ Ohne Lauf stünde der Balken bei −30 % halb draußen; hier steht er still
     und sichtbar am Anfang der Bahn. */
  .jr-mu-go__bar > span { transform: none; }
  /* ⚖️ 31.08.2026 — dieselbe Korrektur wie in der Bewegung: die drei Marken
     stehen auf ANTEILEN der Bahn, nicht auf festen Pixeln. Mit 34/68 px stand
     die dritte auf dem Telefon, sobald die Bahn auf 68 px schrumpfte (390 px
     Breite, gemessen) — im Standbild noch auffälliger als im Lauf. */
  .jr-pr__tok--2 { inset-inline-start: calc(50% - 9px); }
  .jr-pr__tok--3 { inset-inline-start: calc(100% - 18px); }
}

/* ══════════════════════════════════════════════════════════════════════════
   N15-d · THE UPLOAD DOOR'S OWN WAIT — OWNER, 29.08.2026
   ══════════════════════════════════════════════════════════════════════════
   Since N15-b the upload POST carries a model call, so the upload door needs the
   same counter the generate door has had since N3. It is the SAME block —
   `.jr-logo-wait` and its three children are keyed on classes alone, so the
   second one inherits every declaration above, including the load-bearing
   `.jr-logo-wait[hidden] { display: none }` that beats `display: flex`.

   ⇒ EXACTLY ONE DECLARATION IS NEW, and it is spacing. `.jr-logo-send` pays a
   12 px margin above itself and nothing below it, so the counter would sit on
   the button it belongs to. ⛔ Nothing about direction: the row is `display:
   flex`, which mirrors by itself, and the number is a `dir="ltr"` island inside
   it — an RTL rule here would be undoing what the browser already did right.
   ⛔ AT THE END OF THE FILE, like every other block added to this sheet: two
   recorded incidents here came from inserting rules in the middle. */
.jr-logo-wait--upload { margin-block-start: 14px; }

/* ══════════════════════════════════════════════════════════════════════════
   N15-f · THE LANGUAGE SWITCH INSIDE THE CHANNEL WINDOW — OWNER, 29.08.2026
   ══════════════════════════════════════════════════════════════════════════
   «ضيف بهي النافذة زر تبديل اللغات»

   ⭐ IT ADDS NO CONTROL AND NO COLOUR. The markup inside `.jr-cpref__lang` is
   the platform's own `.jr-langmenu`, rendered by the same function the header
   calls, so every declaration it needs — the 38 px pill, the round flag, the
   floating list, the tick on the current language — is already in this sheet
   at line ~541 and is inherited unchanged. What is new here is PLACEMENT and
   nothing else: two rules, and one of them is a stacking order.

   1. THE ROW. `justify-content: flex-end` and not `text-align: right`: flex end
      is the INLINE end, so Arabic mirrors the pill to the other corner with no
      second rule — the same reason every other block in this file states its
      spacing logically. The negative block-start margin pulls the pill up into
      the card's own 22 px of padding, so adding a switch does not push the
      question down; the card keeps the height it has today.

   2. THE OPEN LIST GETS A LAYER OF ITS OWN. It opens downward ACROSS the
      question, the lede and both 64 px choices, all of which carry a background
      here. `.jr-langmenu__list` already says `position: absolute; z-index: 9`,
      and that index resolves against the nearest ancestor that is a stacking
      context — which inside this card is NOT a fixed thing: `.jr-cpmodal
      .jr-cpref` becomes one for the 180 ms its entry animation runs and stops
      being one afterwards. Giving `.jr-langmenu` a `z-index` of its own makes
      the menu that context, so the list's layer is decided by markup rather
      than by when the reader taps relative to an animation.
   ⚠️ ON THE MENU, NOT ON THE LIST. The list is already indexed; what it lacked
      was an ancestor that pins where that index counts.
   ⚖️ REASONED, NOT MEASURED — the paint section of
      `tools/n15e_modal_lang_gate.js` is the thing that settles it in a real
      browser, and it is refused on a host under 3 GB of available memory.

   ⛔ AT THE END OF THE FILE, like every other block added to this sheet: two
   recorded incidents here came from inserting rules in the middle. */
.jr-cpref__lang { display: flex; justify-content: flex-end; margin-block: -6px 8px; }
.jr-cpref__lang .jr-langmenu { z-index: 2; }

/* ══════════════════════════════════════════════════════════════════════════
   ⭐⭐ 29.08.2026 · OWNER — DER ZAUBERSTAB AM «LOGO ERZEUGEN LASSEN»
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ «و زر Logo erzeugen lassen حط بجنبه عصاي سحرية.»

   ⛔ ALS PSEUDO-ELEMENT, NICHT ALS `<svg>` IM KNOPF, und der Grund ist gemessen
   und nicht ästhetisch: zwei Skripte schreiben den Inhalt dieses Knopfes neu.
   `public-i18n.js` hydriert ihn über `[data-i18n]`, und `jr-logo-shrink.js`
   setzt beim Absenden `button.textContent = 'Wird gezeichnet …'`. Beides ersetzt
   JEDES Kind. Ein `::before` überlebt beides und ist per Konstruktion nicht im
   Accessibility-Baum — das Wort im Knopf trägt die Bedeutung, der Stab ist
   Schmuck, und ein Screenreader soll ihn nicht vorlesen.

   ⭐ DIESELBE GEOMETRIE WIE DER WARTEKRINGEL (`.jr-cta.is-busy::before`):
   15 × 15, `margin-inline-end: 9px`, `vertical-align: -2px`. Deshalb springt die
   Beschriftung beim Absenden nicht um einen Pixel — der Stab geht, der Kringel
   kommt, und beide stehen an derselben Stelle.
   ⛔ Und die Busy-Regel GEWINNT von selbst: sie ist zwei Klassen
   (`.jr-cta.is-busy::before`), diese hier ist eine. Es braucht keine dritte
   Regel, die den Stab während des Wartens abschaltet.

   ⭐ `mask-image` + `background: currentColor`, NICHT `background-image` mit
   fester Farbe. Der Knopf trägt das Geist-Kleid (dunkle Tinte auf Weiß), und
   `currentColor` heisst: ändert sich die Tinte je Zustand oder je Thema, geht
   der Stab von selbst mit. Ein eingebrannter Hex-Wert wäre eine zweite Wahrheit
   über eine Farbe.

   🪤 GESPIEGELT IM RTL. Der Stab ist gerichtet (Griff unten-links, Spitze
   oben-rechts) wie ein Pfeil; im Arabischen sitzt er rechts vom Wort und zeigt
   sonst vom Text weg. Regel `feedback_real_icons_rtl_safe`.

   ⛔ AM ENDE DER DATEI, wie jeder Block seit D3 — zwei protokollierte Vorfälle
   hier kamen daher, dass Regeln in die Mitte geschrieben wurden. */
.jr-cta--wand::before {
  content: '';
  display: inline-block;
  width: 15px;
  height: 15px;
  margin-inline-end: 9px;
  vertical-align: -2px;
  background: currentColor;
  -webkit-mask-image: var(--jr-wand);
  mask-image: var(--jr-wand);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
/* ⚖️ 30.08.2026 · OWNER — «ايقونة العصاية السحرية بدي وحدة احترافية مو هي الزبالة»
   ⇒ the hand-drawn wand with three lopsided stars is replaced by the Lucide
   `wand-sparkles` glyph (MIT), unchanged from the icon set: a slanted rod from
   bottom-left to top-right with a short tip mark and six sparkle ticks. Same
   15 × 15 box, same mask mechanics, same `currentColor`, same RTL mirror —
   only the drawing changed. Still directed like an arrow (handle bottom-left,
   tip top-right), so the `scaleX(-1)` below remains correct. */
:root {
  --jr-wand: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72Z'/%3E%3Cpath d='m14 7 3 3'/%3E%3Cpath d='M5 6v4'/%3E%3Cpath d='M19 14v4'/%3E%3Cpath d='M10 2v2'/%3E%3Cpath d='M7 8H3'/%3E%3Cpath d='M21 16h-4'/%3E%3Cpath d='M11 3H9'/%3E%3C/svg%3E");
}
[dir="rtl"] .jr-cta--wand::before { transform: scaleX(-1); }

/* ⚖️ 30.08.2026 · OWNER — «زر Logo erzeugen lassen نزله شوي عن حاوية الادخال»
   The ghost button stood flush under the brief's field box (`#jr-logo-form`
   ends with no bottom margin of its own, and the button carries none). A
   block-start margin on the button itself — not on the form, which four other
   things follow in other states — puts the air where the owner pointed. Logical
   property, so RTL needs nothing. */
.jr-cta--wand { margin-block-start: 18px; }

/* 🔴 OW-1 · 31.08.2026 — HIER STAND `.jr-logo-results__caption`. Die
   Bildunterschrift «Dieses Logo übernehmen» unter den Vorschlagskacheln IST auf
   Anweisung des Inhabers der Knopf geworden («و النص يلي تحت الشعار … يصير هو
   الزر»), also gibt es die Klasse nicht mehr — und eine Regel für eine Klasse,
   die niemand mehr ausgibt, ist genau die tote Zeile, wegen der
   `journey_view_gate` überhaupt existiert. Der Abstand, den sie trug, sitzt
   jetzt in `.jr-logo-offer__cta` weiter unten. */

/* ══════════════════════════════════════════════════════════════════════════
   ⭐ 29.08.2026 · OWNER — TRENNLINIEN IM BLOCK «BETRIEB UND INHABER»
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ «هون المعلومات حطلي بينهم اسطر لحتى يكونو اوضح بصرياً فقط تبع هذا القسم
   Betrieb und Inhaber.»

   Zwölf Paare standen dort ohne jede Zäsur untereinander; das Auge musste die
   Zeile selbst finden, zu der ein Wert gehört. Eine Linie je Zeile beantwortet
   genau das — und nichts sonst.

   🪤 DIE LINIE KANN NICHT AUF DIE ZEILE, WEIL ES KEINE GIBT. `.jr-facts > .jr-kv`
   ist `display: contents` (D5): das Paar löst sich auf, damit Label und Wert
   Teilnehmer EINES Rasters über alle Zeilen werden — das ist es, was die Werte
   miteinander ausrichtet. Ein `display: contents`-Element malt nichts, es hat
   weder Rahmen noch Hintergrund. ⇒ Die Linie sitzt auf seinen beiden KINDERN,
   und weil die im Raster nebeneinander liegen, ergeben die zwei Kanten eine
   durchgehende Linie.
   ⛔ NICHT auf der ersten Zeile: eine Linie direkt unter der Überschrift wäre
   ein Strich um nichts.

   ⛔ UND NUR HIER. `.jr-facts` kommt in der ganzen Auslieferung genau einmal vor
   (`screen_review.php`, Block 1) — der Selektor ist damit von selbst auf den
   Abschnitt begrenzt, den der Inhaber genannt hat. Die Logo-, Zeiten-, Preis-
   und Menü-Kacheln benutzen `.jr-kv` ohne `.jr-facts` und bleiben unberührt. */
.jr-facts > .jr-kv:not(:first-child) > .jr-kv__k,
.jr-facts > .jr-kv:not(:first-child) > .jr-kv__v {
  border-top: 1px solid var(--jr-line);
  padding-top: 7px;
  margin-top: 1px;
}

/* ══════════════════════════════════════════════════════════════════════════
   ⭐ 29.08.2026 · OWNER — «العربية» IM SPRACHMENÜ IN CAIRO
   ══════════════════════════════════════════════════════════════════════════
   ⚖️ «بقائمة اللغات كلمة العربية خليها بخط كايرو.»

   🔬 WARUM SIE ES NICHT SCHON WAR. Die Regel vom 20.08. hängt die arabische
   Schrift an die SEITE: `html[lang="ar"] body.jr-page { font-family: var(--jr-font-ar); }`.
   Das ist für jeden arabischen Bildschirm richtig — und es greift genau dann
   nicht, wenn arabischer Text auf einer NICHT-arabischen Seite steht. Das
   Sprachmenü ist der einzige Ort, an dem das passiert: es zeigt alle fünf Namen
   in ihrer eigenen Schrift, während die Seite deutsch ist.

   ⭐ `:lang(ar)` UND NICHT `[lang="ar"]`, und das ist der Punkt: die Elemente
   tragen `lang="ar"` am Link, die Beschriftung ist ein Kind davon.
   `:lang()` prüft die GEERBTE Sprache und trifft deshalb beide — das Attribut
   allein hätte nur den Link getroffen und die Beschriftung darin verfehlt.
   ⭐ Und es ist dasselbe `lang="ar"`, das seit 19.08. aus WCAG 3.1.2 dort steht
   (Language of Parts) — die Aussprache und die Schrift folgen jetzt derselben
   einen Angabe statt zweier, die auseinanderlaufen können.
   ⛔ Nichts an den anderen vier Sprachen bewegt sich. */
.jr-langmenu__item:lang(ar),
.jr-langmenu__label:lang(ar) {
  font-family: var(--jr-font-ar);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ⭐⭐⭐ SPEISEKARTE · DESIGN-EINBAU (Claude Design, 30.08.2026 · Inhaber-Auftrag)
   Quelle: C:\tmp\_b6gate_9594\extract\design_handoff_speisekarte_station\
   (README.md = Werte, SpeisekarteStation.dc.html = Markup, PhotoScan.dc.html
   und MenuTyping.dc.html = die zwei Animationen). Hifi: Farben, Maße, Radien,
   Schatten und Zeiten stehen im README und werden hier wörtlich übernommen.

   ⛔ NUR DIESE STATION: alles hängt unter `[data-jr-screen="menue_upload"]`.
   Die Töne der Lieferung (warme Neutralen #f8f4f4 …, Akzent-Rampe) stehen als
   `--mu-*` auf der Sektion — die Reise-Chrome (Streifen, Kopf, Fuß) behält ihre
   eigenen Töne, damit die anderen sechzehn Stationen nicht mitwandern.
   ⛔ Die MECHANIK ist unverändert (N15): `<label for>` über dem Dateifeld,
   skriptloser Sende-Knopf, Korb aus dem Server, roter `.jr-cta`, das Fragefenster
   (`.jr-mu-ask`, weiter oben, unberührt). Nur das Blatt sieht anders aus.
   ⛔ LOGISCH GESCHRIEBEN (inline/block, start/end): Arabisch spiegelt sich von
   selbst; die zwei Pfeile, die eine RICHTUNG meinen, werden per `[dir="rtl"]`
   gedreht — CSS, nie Markup (n12-Gate D7).
   ⭐ Bewegung ist Dekoration: `prefers-reduced-motion: reduce` hält alle
   Schleifen auf ihrem ersten Bild an (README §Behavior).
   ═══════════════════════════════════════════════════════════════════════════ */
[data-jr-screen="menue_upload"] {
  --mu-n100: #f8f4f4; --mu-n200: #eae7e7; --mu-n300: #d7d3d3; --mu-n400: #bab6b6;
  --mu-n500: #9b9797; --mu-n600: #7d7979; --mu-n700: #605d5d; --mu-n800: #444141;
  --mu-a100: #fff2ef; --mu-a200: #ffe0d9; --mu-a300: #ffc4b8; --mu-a500: #ff563c;
  --mu-a600: #dd2b0f; --mu-a700: #ae1800;
  --mu-ink: #201e1d;
  --mu-shadow-sm: 0 1px 2px rgba(45, 43, 43, .14);
  --mu-shadow-md: 0 3px 10px rgba(45, 43, 43, .16);
  --mu-r-card: 20px; --mu-r-note: 14px; --mu-r-know: 18px;
  --mu-gap: 20px;
  display: flex; flex-direction: column; gap: var(--mu-gap);
  color: var(--mu-ink);
}
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] { --mu-r-card: 22px; --mu-r-note: 16px; --mu-r-know: 20px; --mu-gap: 26px; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] { --mu-r-card: 24px; --mu-r-note: 18px; --mu-r-know: 22px; --mu-gap: 34px; }
}

/* ── Kopf: Kicker · H1 · Lede ──────────────────────────────────────────────── */
.jr-mu-hero { display: flex; flex-direction: column; gap: 8px; }
.jr-mu-hero__kicker {
  font-family: inherit; font-weight: 600; font-size: 10px; line-height: 1.4;
  letter-spacing: .22em; text-transform: uppercase; color: var(--mu-a700);
}
[data-jr-screen="menue_upload"] .jr-h1.jr-mu-hero__t {
  margin: 0; font-size: 32px; line-height: 1.1; letter-spacing: -.02em; font-weight: 600; color: var(--mu-ink);
}
[data-jr-screen="menue_upload"] .jr-lede.jr-mu-hero__lede {
  margin: 0; font-size: 15px; line-height: 1.55; color: var(--mu-n700); max-width: 52ch;
}
@media (min-width: 834px) {
  .jr-mu-hero { gap: 10px; }
  .jr-mu-hero__kicker { font-size: 11px; }
  [data-jr-screen="menue_upload"] .jr-h1.jr-mu-hero__t { font-size: 42px; line-height: 1.06; }
  [data-jr-screen="menue_upload"] .jr-lede.jr-mu-hero__lede { font-size: 17px; line-height: 1.5; }
}
@media (min-width: 1280px) {
  .jr-mu-hero { gap: 12px; }
  [data-jr-screen="menue_upload"] .jr-h1.jr-mu-hero__t { font-size: 54px; line-height: 1.04; letter-spacing: -.025em; }
  [data-jr-screen="menue_upload"] .jr-lede.jr-mu-hero__lede { font-size: 19px; }
}
/* Arabisch: keine negativen Laufweiten, ruhigere Zeilen (Cairo) — die
   Seitenregel `body[dir="rtl"] *` setzt letter-spacing bereits zurück. */
body.jr-page[dir="rtl"] [data-jr-screen="menue_upload"] .jr-h1.jr-mu-hero__t { line-height: 1.3; }

/* ── Art.-13-Hinweis ───────────────────────────────────────────────────────── */
[data-jr-screen="menue_upload"] .jr-card.jr-mu-note {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 13px 14px; border: 0; border-radius: var(--mu-r-note);
  background: var(--mu-n100);
}
.jr-mu-note__icon { flex: none; margin-block-start: 1px; inline-size: 17px; block-size: 17px; color: var(--mu-n600); }
.jr-mu-note__body { display: flex; flex-wrap: wrap; gap: 0 .35em; min-inline-size: 0; }
/* ⚖️ Der Satz bleibt in voller Größe (n12-Gate D10) — nur der Rahmen ist leiser. */
[data-jr-screen="menue_upload"] .jr-mu-note .jr-card__text {
  margin: 0; font-size: 13px; line-height: 1.55; color: var(--mu-n800);
}
.jr-mu-note__link {
  font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.55;
  color: var(--mu-a700); text-decoration: underline; text-underline-offset: 3px;
}
.jr-mu-note__link:hover { color: var(--jr-accent); }
.jr-mu-note__link:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 2px; border-radius: 4px; }
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-note { gap: 13px; padding: 15px 18px; }
  .jr-mu-note__icon { inline-size: 18px; block-size: 18px; margin-block-start: 2px; }
  [data-jr-screen="menue_upload"] .jr-mu-note .jr-card__text, .jr-mu-note__link { font-size: 14px; line-height: 1.6; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-note { gap: 14px; padding: 18px 22px; }
  .jr-mu-note__icon { inline-size: 19px; block-size: 19px; }
  [data-jr-screen="menue_upload"] .jr-mu-note .jr-card__text, .jr-mu-note__link { font-size: 15px; }
}

/* ── Die zwei Wege ─────────────────────────────────────────────────────────── */
[data-jr-screen="menue_upload"] .jr-choices {
  display: grid; grid-template-columns: 1fr; gap: 18px; margin: 0;
}
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] .jr-choices { grid-template-columns: 1fr 1fr; gap: 18px; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] .jr-choices { gap: 24px; }
}
/* ⭐ Das Formular ist die Zelle; die Karte füllt sie. Der skriptlose Sende-Knopf
   steht unter der Karte (Spalte), mit Skript ist er `hidden`. */
[data-jr-screen="menue_upload"] .jr-choice-form { display: flex; flex-direction: column; gap: 10px; margin: 0; min-inline-size: 0; }
.jr-choice-form--stack { flex-direction: column; }
/* ⛔ journey_view_gate: jede ausgegebene Klasse braucht eine eigene Regel. Die
   drei Namen tragen die Reihenfolge der zwei Wege (empfohlen zuerst) — die Form
   selbst kommt aus der Rasterzelle. */
.jr-choice-form--rec { order: 1; }
.jr-choice-form--man { order: 2; }
.jr-choice--rec { color: var(--mu-ink, #201e1d); }
/* ⚠️ Eine Tastatur muss sehen, wo sie ist: das Feld ist `.jr-clip`, den Ring
   zeichnet die Karte, die dafür einsteht (dieselbe Lösung wie `.jr-drop`). */
.jr-choice-form--stack:focus-within .jr-mu-card { outline: 2px solid var(--jr-accent); outline-offset: 2px; }
.jr-mu__send { min-height: 44px; font-size: 15px; }
.jr-mu__send[hidden] { display: none; }

/* Die Karte — beide Wege teilen die Form, der empfohlene trägt den Akzent. */
[data-jr-screen="menue_upload"] .jr-choice.jr-mu-card {
  position: relative;
  display: flex; flex-direction: column; align-items: stretch; gap: 14px;
  /* 🪤 `.jr-choice` (:713, die Umschaltknöpfe der Zeiten-Station) setzt `height: 48px`
     — eine definite Höhe, die die Karte auf 48 px zusammenzog und ihren Inhalt
     über den Zähler laufen ließ (gemessen 30.08.2026, erstes Foto). `auto` hier
     ist Pflicht, nicht Stil. */
  inline-size: 100%; flex: 1 1 auto; min-block-size: 0; block-size: auto; height: auto;
  padding: 22px 18px 20px;
  border: 1px solid var(--mu-n200); border-radius: var(--mu-r-card);
  background: #ffffff; color: var(--mu-ink);
  font: inherit; text-align: start; cursor: pointer;
  transition: transform .2s ease, box-shadow .2s ease;
}
[data-jr-screen="menue_upload"] .jr-choice.jr-mu-card:hover { background: #ffffff; border-color: var(--mu-n200); transform: translateY(-3px); box-shadow: var(--mu-shadow-md); }
[data-jr-screen="menue_upload"] .jr-choice.jr-mu-card:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 2px; }
[data-jr-screen="menue_upload"] .jr-choice.jr-mu-card--rec { padding: 24px 18px 20px; border: 1.5px solid var(--mu-a300); background: var(--mu-a100); }
[data-jr-screen="menue_upload"] .jr-choice.jr-mu-card--rec:hover { background: var(--mu-a100); border-color: var(--mu-a300); }
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card { padding: 26px 24px 24px; gap: 16px; }
  [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card--rec { padding: 26px 24px 24px; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card { padding: 32px 32px 30px; gap: 20px; }
  [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card--rec { padding: 32px 32px 30px; }
}
/* „Empfohlen" schwebt auf der Kante. */
[data-jr-screen="menue_upload"] .jr-choice__badge.jr-mu-card__badge {
  position: absolute; inset-block-start: -11px; inset-inline-start: 18px;
  margin: 0; padding: 5px 12px; border-radius: 999px;
  background: var(--jr-accent); color: #ffffff;
  font-family: inherit; font-weight: 600; font-size: 10px; line-height: 1.2; letter-spacing: .09em;
}
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] .jr-choice__badge.jr-mu-card__badge { inset-block-start: -12px; inset-inline-start: 24px; padding: 5px 13px; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] .jr-choice__badge.jr-mu-card__badge { inset-block-start: -13px; inset-inline-start: 32px; padding: 6px 15px; font-size: 11px; }
}
/* Überschrift und Satz der Karte. `.jr-choice__label` bleibt der Knoten, in den
   jr-menu-photos.js das Wort „Wird hochgeladen …" schreibt. */
[data-jr-screen="menue_upload"] .jr-choice__label.jr-mu-card__t {
  display: block; margin: 0;
  font-family: inherit; font-weight: 600; font-size: 20px; line-height: 1.2; letter-spacing: -.01em; color: var(--mu-ink);
}
[data-jr-screen="menue_upload"] .jr-choice__hint.jr-mu-card__p {
  display: block; margin: 0;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.6; color: var(--mu-n800);
}
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] .jr-choice__label.jr-mu-card__t { font-size: 22px; line-height: 1.18; letter-spacing: -.015em; }
  [data-jr-screen="menue_upload"] .jr-choice__hint.jr-mu-card__p { font-size: 14px; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] .jr-choice__label.jr-mu-card__t { font-size: 26px; line-height: 1.16; }
  [data-jr-screen="menue_upload"] .jr-choice__hint.jr-mu-card__p { font-size: 15px; line-height: 1.65; }
}
/* Der Knopf in der Karte ist ein SPAN: ein echter <button> in einem <label>
   nähme dem Label den Klick — und ohne Skript öffnet genau das Label die Kamera. */
.jr-mu-card__cta {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-block-start: auto;
  inline-size: 100%; min-block-size: 50px; padding: 0 20px;
  border-radius: 999px;
  font-family: inherit; font-weight: 600; font-size: 15px; line-height: 1.2;
  white-space: nowrap;
  transition: background .18s ease, border-color .18s ease;
}
.jr-mu-card__cta--primary { background: var(--jr-accent); color: #ffffff; box-shadow: var(--mu-shadow-sm); }
.jr-mu-card--rec:hover .jr-mu-card__cta--primary { background: var(--mu-a600); }
.jr-mu-card--rec:active .jr-mu-card__cta--primary { background: var(--mu-a700); }
.jr-mu-card__cta--secondary { background: #ffffff; color: var(--mu-ink); border: 1px solid var(--mu-n300); }
.jr-mu-card--man:hover .jr-mu-card__cta--secondary { background: var(--mu-n100); border-color: var(--mu-n400); }
.jr-mu-card__cta svg { flex: none; inline-size: 16px; block-size: 16px; }
/* ⭐ Der Pfeil zeigt in Leserichtung — auf Arabisch nach links. CSS, nie Markup. */
body.jr-page[dir="rtl"] .jr-mu-card__cta svg { transform: scaleX(-1); }
@media (min-width: 834px) {
  .jr-mu-card__cta { inline-size: auto; align-self: flex-start; justify-content: flex-start; min-block-size: 46px; padding: 12px 20px; font-size: 14px; }
  .jr-mu-card__cta svg { inline-size: 15px; block-size: 15px; }
}
@media (min-width: 1280px) {
  .jr-mu-card__cta { min-block-size: 0; padding: 14px 24px; font-size: 15px; }
  .jr-mu-card__cta--secondary { padding: 13px 23px; }
  .jr-mu-card__cta svg { inline-size: 16px; block-size: 16px; }
}

/* ── Das Bild der Karte: Bühne für die Animation ───────────────────────────── */
.jr-mu-card__art {
  display: flex; justify-content: center; align-items: flex-start;
  inline-size: 100%; block-size: 146px; overflow: visible;
}
.jr-mu-card__art--type { block-size: 112px; align-items: flex-end; }
.jr-mu-card__art--type .jr-mt { margin-inline: auto; }
@media (min-width: 834px) {
  .jr-mu-card__art { block-size: 152px; justify-content: flex-start; }
  .jr-mu-card__art--type { block-size: 152px; }
  .jr-mu-card__art--type .jr-mt { margin-inline: 0; }
}
/* ══════════════════════════════════════════════════════════════════════════
   🔴🔴 MU-4 · 30.08.2026 · INHABER — „صغرتا كتير هيك على الديسكتوب !!
   لازم يكون لكل حجم شاشة حجم مناسب للصورة !!"
   ══════════════════════════════════════════════════════════════════════════
   🔬 GEMESSEN AM 30.08.2026 auf der Live-Station, vier Breiten × vierzehn Höhen.
   Die vier festen Stufen (118 · 190 · 228 · 268 px) waren an den Rändern GENAU
   VERKEHRT herum, und beides ließ sich zeigen:

     1920×1000 → Bild 118 px und 90 px Luft blieben ungenutzt   ← die Klage
     1920×1040 → Bild 190 px und die Seite ROLLTE  (−32 px)
     1920×1300 → Bild 228 px und 190 px Luft blieben ungenutzt
     1920×1317 → Bild 268 px und die Seite ROLLTE  (−10 px)
     1280×1200 → Streifen 597 px breit IN EINER 468 px BREITEN KARTE (Überlauf)

   ⇒ Die Stufe hing an einer Zahl, die mit dem Platz nichts zu tun hatte. Jetzt
   hängt sie an dem, was wirklich zählt, und zwar an BEIDEM:

     `--mu-kw`  wieviel BREITE die Karte hat  = (Kartenbreite − 12) / 452
     `--mu-kh`  wieviel LUFT unter dem Fuß bleibt = (Fensterhöhe − Rest − 8) / 173
     `--mu-k`   = clamp(.72, min(kw, kh), 1.64)     ⇒ was nie überläuft

   `--mu-k` ist der EINZIGE Regler: Bildhöhe = 173 px × k, Foto-Weg = ×k,
   Tastatur = ×k×1,15 (dasselbe Verhältnis wie in der Lieferung, 1,25/1,1).
   ⛔ 452 px ist die natürliche Streifenbreite, 173 px die natürliche Bildhöhe —
   beide aus der Lieferung, beide nachgemessen. Die Zeichnungen selbst sind
   UNBERÜHRT: `.jr-ps`/`.jr-mt` werden skaliert, nicht neu gezeichnet.
   ⭐ Und weil `min()` und `clamp()` mit reinen Zahlen rechnen, steht die Formel
   EINMAL — die zwei Leitern darunter setzen nur noch je einen Wert.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] {
    --mu-kw: 1.00;
    --mu-kh: .68;
    --mu-k: clamp(.68, min(var(--mu-kw), var(--mu-kh)), 1.64);
  }
  .jr-mu-card__art, .jr-mu-card__art--type { block-size: calc(173px * var(--mu-k)); }
  /* 🪤 Der Maßstab von `.jr-ps` steht NICHT hier, sondern in der letzten Regel
     des Blattes, die `.jr-ps` anfasst (Suche: `--ps-gap: 20px`): die Regel für
     834 px steht später und gewönne sonst mit ×,92. `.jr-mt` hat kein solches
     Gegenstück, deshalb darf sie hier stehen. */
  .jr-mu-card__art--type .jr-mt { transform: scale(calc(var(--mu-k) * 1.15)); transform-origin: bottom left; }
  body.jr-page[dir="rtl"] .jr-mu-card__art--type .jr-mt { transform-origin: bottom right; }
}
/* ── Leiter 1 · die BREITE der Karte (gemessen: Karte = Fenster/2 − 116 px, bis
   sie bei 1856 px stehen bleibt; innen 56 px Polster, 12 px Sicherheit). ⛔ Der
   Wert einer Stufe ist der ihres UNTEREN Randes — so läuft nichts über. */
@media (min-width: 1360px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.09; } }
@media (min-width: 1440px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.18; } }
@media (min-width: 1520px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.27; } }
@media (min-width: 1600px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.36; } }
@media (min-width: 1680px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.45; } }
@media (min-width: 1760px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.53; } }
@media (min-width: 1856px) { [data-jr-screen="menue_upload"] { --mu-kw: 1.64; } }
/* ── Leiter 2 · die LUFT unter dem Fuß. Der „Rest" (alles außer dem Bild) wurde
   gemessen und hängt nur von der Breite ab, weil die Sätze dort umbrechen:
   844 px bis 1439 · 825 px bis 1599 · 792 px darüber. Schritt: 20 px Fensterhöhe.
   ⛔ Über ~1100 px Höhe steht kh ohnehin über kw — deshalb endet die Leiter dort. */
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 980px) { [data-jr-screen="menue_upload"] { --mu-kh: .74; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1000px) { [data-jr-screen="menue_upload"] { --mu-kh: .85; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1020px) { [data-jr-screen="menue_upload"] { --mu-kh: .97; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1040px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.08; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1060px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.20; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1080px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.31; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1100px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.43; } }
@media (min-width: 1280px) and (max-width: 1439px) and (min-height: 1120px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.64; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 960px) { [data-jr-screen="menue_upload"] { --mu-kh: .73; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 980px) { [data-jr-screen="menue_upload"] { --mu-kh: .84; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 1000px) { [data-jr-screen="menue_upload"] { --mu-kh: .96; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 1020px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.08; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 1040px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.19; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 1060px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.31; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 1080px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.42; } }
@media (min-width: 1440px) and (max-width: 1599px) and (min-height: 1100px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.64; } }
@media (min-width: 1600px) and (min-height: 940px) { [data-jr-screen="menue_upload"] { --mu-kh: .80; } }
@media (min-width: 1600px) and (min-height: 960px) { [data-jr-screen="menue_upload"] { --mu-kh: .92; } }
@media (min-width: 1600px) and (min-height: 980px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.04; } }
@media (min-width: 1600px) and (min-height: 1000px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.15; } }
@media (min-width: 1600px) and (min-height: 1020px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.27; } }
@media (min-width: 1600px) and (min-height: 1040px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.38; } }
@media (min-width: 1600px) and (min-height: 1060px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.50; } }
@media (min-width: 1600px) and (min-height: 1080px) { [data-jr-screen="menue_upload"] { --mu-kh: 1.64; } }

/* ── PhotoScan — drei Bilder, zwei Pfeile (README §Phase strip) ────────────── */
.jr-ps {
  --ps-gap: 6px; --ps-line: 0px;
  display: flex; align-items: flex-start; gap: var(--ps-gap);
  inline-size: 348px; flex: none;
  transform: scale(.88); transform-origin: top center;
}
@media (min-width: 834px) {
  .jr-ps { transform: scale(.92); transform-origin: top left; }
  body.jr-page[dir="rtl"] .jr-ps { transform-origin: top right; }
}
@media (min-width: 1280px) {
  /* 🪤 MU-4 · 30.08.2026 — HIER STAND `transform: none`, und weil diese Regel
     SPÄTER kommt als die Maßstabsregel, hob sie `--mu-k` lautlos auf: das Bild
     wurde höher, die Zeichnung blieb klein. Genau die Kaskade, die schon K-3
     aufgeschrieben hat. Der Maßstab gehört jetzt an EINE Stelle, und das ist
     nicht diese. */
  .jr-ps {
    --ps-gap: 20px; --ps-line: 26px; inline-size: 452px;
    transform: scale(var(--mu-k)); transform-origin: top left;
  }
  body.jr-page[dir="rtl"] .jr-ps { transform-origin: top right; }
}
.jr-ps__step { display: flex; flex-direction: column; align-items: center; gap: 6px; inline-size: 96px; flex: none; }
.jr-ps__num {
  display: grid; place-items: center; flex: none;
  inline-size: 20px; block-size: 20px; border-radius: 999px;
  background: var(--jr-accent); color: #ffffff;
  font-family: inherit; font-weight: 600; font-size: 11px; line-height: 1; font-variant-numeric: tabular-nums;
}
.jr-ps__panel {
  position: relative; inline-size: 96px; block-size: 100px; border-radius: 16px; overflow: hidden;
  background: linear-gradient(180deg, var(--mu-n100), var(--mu-n200));
  direction: ltr; /* das Bild ist gezeichnet, nicht gelesen — es spiegelt sich nicht */
}
.jr-ps__cap {
  display: block; text-align: center;
  font-family: inherit; font-weight: 500; font-size: 11.5px; line-height: 1.35; color: var(--mu-n700);
}
.jr-ps__arrow { display: flex; align-items: center; gap: 1px; flex: none; margin-block-start: 68px; }
.jr-ps__line { display: block; inline-size: var(--ps-line); block-size: 2px; border-radius: 999px; background: var(--mu-n400); }
.jr-ps__arrow svg { flex: none; inline-size: 17px; block-size: 17px; margin-inline-start: -3px; color: var(--mu-n400); }
body.jr-page[dir="rtl"] .jr-ps__arrow svg { transform: scaleX(-1); }

/* Phase 1 — schreiben */
.jr-ps__sheet {
  position: absolute; left: 18px; top: 14px; inline-size: 60px; block-size: 72px; border-radius: 8px;
  background: #ffffff; box-shadow: var(--mu-shadow-sm);
  padding: 10px 9px; display: flex; flex-direction: column; gap: 7px; transform: rotate(-3deg);
}
.jr-ps__title { display: block; inline-size: 22px; block-size: 4px; border-radius: 999px; background: var(--mu-n800); }
.jr-ps__ln { display: block; block-size: 3.5px; border-radius: 999px; background: var(--mu-n400); inline-size: 0; }
.jr-ps__ln--a { animation: jr-ps-1a 5.4s steps(10, end) infinite; }
.jr-ps__ln--b { animation: jr-ps-1b 5.4s steps(8, end) infinite; }
.jr-ps__ln--c { animation: jr-ps-1c 5.4s steps(9, end) infinite; }
.jr-ps__pen {
  position: absolute; left: 44px; top: 34px; display: block;
  animation: jr-ps-1pen 5.4s cubic-bezier(.5, 0, .3, 1) infinite;
  filter: drop-shadow(0 2px 3px rgba(45, 43, 43, .22));
}
.jr-ps__pen svg { inline-size: 22px; block-size: 22px; display: block; }
@keyframes jr-ps-1a { 0% { width: 0 } 18% { width: 34px } 88% { width: 34px } 100% { width: 0 } }
@keyframes jr-ps-1b { 0%, 18% { width: 0 } 36% { width: 26px } 88% { width: 26px } 100% { width: 0 } }
@keyframes jr-ps-1c { 0%, 36% { width: 0 } 54% { width: 30px } 88% { width: 30px } 100% { width: 0 } }
@keyframes jr-ps-1pen {
  0% { transform: translate(0, 0) rotate(-14deg) } 18% { transform: translate(26px, 0) rotate(-14deg) }
  21% { transform: translate(0, 11px) rotate(-14deg) } 36% { transform: translate(19px, 11px) rotate(-14deg) }
  39% { transform: translate(0, 22px) rotate(-14deg) } 54% { transform: translate(23px, 22px) rotate(-14deg) }
  100% { transform: translate(23px, 22px) rotate(-14deg) }
}

/* Phase 2 — fotografieren / hochladen (zwei Szenen, harter Schnitt bei 49,5 %) */
.jr-ps__scene { position: absolute; inset: 0; }
.jr-ps__scene--a { opacity: 1; animation: jr-ps-2A 8.8s linear infinite both; }
.jr-ps__scene--b { opacity: 0; animation: jr-ps-2B 8.8s linear infinite both; }
.jr-ps__paper {
  position: absolute; left: 6px; top: 26px; inline-size: 34px; block-size: 44px; border-radius: 6px;
  background: #ffffff; box-shadow: var(--mu-shadow-sm);
  padding: 7px 6px; display: flex; flex-direction: column; gap: 4px; transform: rotate(-7deg);
}
.jr-ps__paper > span { display: block; block-size: 2.5px; border-radius: 999px; background: var(--mu-n300); }
.jr-ps__paper > span:first-child { inline-size: 14px; block-size: 3px; background: var(--mu-n800); }
.jr-ps__paper > span:nth-child(2) { inline-size: 20px; }
.jr-ps__paper > span:nth-child(3) { inline-size: 16px; }
.jr-ps__paper > span:nth-child(4) { inline-size: 19px; }
.jr-ps__phone {
  position: absolute; right: 14px; top: 8px; inline-size: 46px; block-size: 86px; border-radius: 13px;
  border: 2.5px solid var(--mu-n800); background: #ffffff;
  padding: 6px 5px 5px; display: flex; flex-direction: column; gap: 4px; align-items: center;
  box-shadow: var(--mu-shadow-md);
  animation: jr-ps-2phone 4.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
.jr-ps__ear { display: block; flex: none; inline-size: 16px; block-size: 3px; border-radius: 999px; background: var(--mu-n800); }
.jr-ps__key { position: absolute; display: block; inline-size: 2px; border-radius: 999px; background: var(--mu-n800); }
.jr-ps__key--l { left: -4.5px; top: 22px; block-size: 9px; }
.jr-ps__key--r1 { right: -4.5px; top: 18px; block-size: 7px; }
.jr-ps__key--r2 { right: -4.5px; top: 29px; block-size: 13px; }
.jr-ps__view { position: relative; flex: none; inline-size: 100%; block-size: 44px; border-radius: 7px; background: var(--mu-n100); overflow: hidden; }
.jr-ps__view-sheet { position: absolute; left: 8px; top: 6px; inline-size: 19px; block-size: 32px; border-radius: 3px; background: #ffffff; box-shadow: var(--mu-shadow-sm); display: block; }
.jr-ps__corner { position: absolute; display: block; inline-size: 10px; block-size: 10px; }
.jr-ps__corner--tl { left: 5px; top: 4px; border-top: 2px solid var(--jr-accent); border-left: 2px solid var(--jr-accent); border-top-left-radius: 5px; }
.jr-ps__corner--tr { right: 5px; top: 4px; border-top: 2px solid var(--jr-accent); border-right: 2px solid var(--jr-accent); border-top-right-radius: 5px; }
.jr-ps__corner--bl { left: 5px; bottom: 4px; border-bottom: 2px solid var(--jr-accent); border-left: 2px solid var(--jr-accent); border-bottom-left-radius: 5px; }
.jr-ps__corner--br { right: 5px; bottom: 4px; border-bottom: 2px solid var(--jr-accent); border-right: 2px solid var(--jr-accent); border-bottom-right-radius: 5px; }
.jr-ps__flash { position: absolute; inset: 0; display: block; background: #ffffff; opacity: 0; animation: jr-ps-2flash 4.4s linear infinite; }
.jr-ps__shutter { display: block; flex: none; inline-size: 15px; block-size: 15px; border-radius: 999px; border: 2px solid var(--jr-accent); background: var(--mu-a200); animation: jr-ps-2shut 4.4s ease-in-out infinite; }
.jr-ps__home { display: block; flex: none; inline-size: 16px; block-size: 2.5px; border-radius: 999px; background: var(--mu-n400); margin-block-start: 1px; }
.jr-ps__zone {
  position: absolute; left: 16px; top: 14px; inline-size: 64px; block-size: 56px; border-radius: 14px;
  border: 1.5px solid var(--mu-a300); background: var(--mu-a100); overflow: hidden; display: grid; place-items: center;
}
.jr-ps__up { display: block; animation: jr-ps-2arrow 8.8s linear infinite; }
.jr-ps__up svg { display: block; inline-size: 22px; block-size: 22px; color: var(--jr-accent); }
.jr-ps__okwrap { position: absolute; inset: 0; display: grid; place-items: center; z-index: 2; pointer-events: none; }
.jr-ps__ok { display: grid; place-items: center; inline-size: 28px; block-size: 28px; border-radius: 999px; background: var(--jr-accent); box-shadow: var(--mu-shadow-sm); opacity: 0; animation: jr-ps-2ok 8.8s ease-out infinite; }
.jr-ps__ok svg { inline-size: 16px; block-size: 16px; display: block; }
.jr-ps__doc {
  position: absolute; left: 19px; top: 26px; inline-size: 26px; block-size: 32px; border-radius: 5px;
  background: #ffffff; box-shadow: var(--mu-shadow-sm); padding: 5px; display: flex; flex-direction: column; gap: 3px;
  opacity: 0; animation: jr-ps-2doc 8.8s cubic-bezier(.4, 0, .3, 1) infinite;
}
.jr-ps__doc > span { display: block; block-size: 2.5px; border-radius: 999px; background: var(--mu-n300); }
.jr-ps__doc > span:first-child { inline-size: 11px; block-size: 3px; background: var(--mu-a500); }
.jr-ps__doc > span:nth-child(2) { inline-size: 15px; }
.jr-ps__doc > span:nth-child(3) { inline-size: 12px; }
.jr-ps__doc > span:nth-child(4) { inline-size: 14px; }
.jr-ps__bar { position: absolute; left: 26px; top: 80px; display: block; inline-size: 44px; block-size: 4px; border-radius: 999px; background: var(--mu-n300); }
.jr-ps__bar--fill { inline-size: 0; background: var(--jr-accent); animation: jr-ps-2bar 8.8s linear infinite; }
@keyframes jr-ps-2phone { 0% { transform: scale(1.05) } 22% { transform: scale(1) } 100% { transform: scale(1) } }
@keyframes jr-ps-2flash { 0%, 48% { opacity: 0 } 54% { opacity: .95 } 68% { opacity: 0 } 100% { opacity: 0 } }
@keyframes jr-ps-2shut { 0%, 44% { transform: scale(1) } 52% { transform: scale(.8) } 62% { transform: scale(1) } 100% { transform: scale(1) } }
@keyframes jr-ps-2A { 0% { opacity: 1 } 49.4% { opacity: 1 } 49.5% { opacity: 0 } 99.9% { opacity: 0 } 100% { opacity: 1 } }
@keyframes jr-ps-2B { 0% { opacity: 0 } 49.4% { opacity: 0 } 49.5% { opacity: 1 } 99.9% { opacity: 1 } 100% { opacity: 0 } }
@keyframes jr-ps-2doc {
  0%, 51% { transform: translateY(10px); opacity: 0 }
  57% { transform: translateY(4px); opacity: 1 }
  73% { transform: translateY(-14px); opacity: 1 }
  78% { transform: translateY(-20px); opacity: 0 }
  100% { transform: translateY(10px); opacity: 0 }
}
@keyframes jr-ps-2bar { 0%, 57% { width: 0 } 79% { width: 44px } 99.9% { width: 44px } 100% { width: 0 } }
@keyframes jr-ps-2arrow { 0% { opacity: 1 } 79.9% { opacity: 1 } 80% { opacity: 0 } 99.9% { opacity: 0 } 100% { opacity: 1 } }
@keyframes jr-ps-2ok {
  0% { opacity: 0; transform: scale(.6) } 79.9% { opacity: 0; transform: scale(.6) }
  80% { opacity: 1; transform: scale(.8) } 84% { opacity: 1; transform: scale(1) }
  99.9% { opacity: 1; transform: scale(1) } 100% { opacity: 0; transform: scale(.6) }
}

/* Phase 3 — abtippen */
.jr-ps__done {
  position: absolute; left: 20px; top: 12px; inline-size: 56px; block-size: 76px; border-radius: 8px;
  background: #ffffff; box-shadow: var(--mu-shadow-sm); padding: 10px 9px; display: flex; flex-direction: column; gap: 6px;
}
.jr-ps__done > span { display: block; block-size: 3.5px; border-radius: 999px; background: var(--mu-n300); }
.jr-ps__done > span.jr-ps__cat { block-size: 5px; background: var(--mu-a300); }
.jr-ps__done > span:nth-child(1) { inline-size: 26px; }
.jr-ps__done > span:nth-child(2) { inline-size: 38px; }
.jr-ps__done > span:nth-child(3) { inline-size: 31px; }
.jr-ps__done > span:nth-child(4) { inline-size: 20px; margin-block-start: 2px; }
.jr-ps__done > span:nth-child(5) { inline-size: 35px; }
.jr-ps__frame { position: absolute; inset: 10px; animation: jr-ps-3frame 3.6s ease-in-out infinite; }
.jr-ps__frame > span { position: absolute; display: block; inline-size: 15px; block-size: 15px; }
.jr-ps__frame > span:nth-child(1) { left: 0; top: 0; border-top: 2.5px solid var(--jr-accent); border-left: 2.5px solid var(--jr-accent); border-top-left-radius: 7px; }
.jr-ps__frame > span:nth-child(2) { right: 0; top: 0; border-top: 2.5px solid var(--jr-accent); border-right: 2.5px solid var(--jr-accent); border-top-right-radius: 7px; }
.jr-ps__frame > span:nth-child(3) { left: 0; bottom: 0; border-bottom: 2.5px solid var(--jr-accent); border-left: 2.5px solid var(--jr-accent); border-bottom-left-radius: 7px; }
.jr-ps__frame > span:nth-child(4) { right: 0; bottom: 0; border-bottom: 2.5px solid var(--jr-accent); border-right: 2.5px solid var(--jr-accent); border-bottom-right-radius: 7px; }
.jr-ps__scan {
  position: absolute; left: 28px; right: 28px; top: 16px; display: block; block-size: 2px; border-radius: 999px;
  background: var(--jr-accent); box-shadow: 0 0 10px 2px rgba(236, 48, 19, .4);
  opacity: 0; animation: jr-ps-3scan 3.6s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes jr-ps-3scan { 0% { transform: translateY(0); opacity: 0 } 10% { opacity: 1 } 84% { opacity: 1 } 100% { transform: translateY(62px); opacity: 0 } }
@keyframes jr-ps-3frame { 0%, 100% { transform: scale(1) } 50% { transform: scale(.95) } }

/* ── MenuTyping — die Tastatur (README §Keyboard strip) ────────────────────── */
.jr-mt {
  position: relative; inline-size: 160px; block-size: 112px; border-radius: 20px; overflow: hidden; flex: none;
  background: linear-gradient(180deg, var(--mu-n100), var(--mu-n200));
  padding: 10px; display: flex; flex-direction: column; gap: 6px;
  direction: ltr;
}
.jr-mt__form { border-radius: 10px; background: #ffffff; box-shadow: var(--mu-shadow-sm); padding: 8px 10px; display: flex; flex-direction: column; gap: 5px; }
.jr-mt__row { display: flex; align-items: center; gap: 5px; }
.jr-mt__row > span { display: block; block-size: 5px; border-radius: 999px; }
.jr-mt__hd { inline-size: 20px; background: var(--mu-n800); }
.jr-mt__hd2 { inline-size: 10px; background: var(--mu-n300); }
.jr-mt__ln { inline-size: 0; background: var(--mu-n400); }
.jr-mt__ln--a { animation: jr-mt-a 5.6s steps(13, end) infinite; }
.jr-mt__ln--b { animation: jr-mt-b 5.6s steps(10, end) infinite; }
.jr-mt__tag { inline-size: 14px; background: var(--mu-a300); }
.jr-mt__caret { inline-size: 2px; block-size: 9px; border-radius: 1px; background: var(--jr-accent); animation: jr-mt-caret 1s step-end infinite; }
.jr-mt__price { margin-inline-start: auto; inline-size: 16px; block-size: 7px; border-radius: 3px; background: var(--mu-a200); opacity: 0; animation: jr-mt-price 5.6s ease-out infinite; }
.jr-mt__kb { border-radius: 10px; background: #ffffff; box-shadow: var(--mu-shadow-sm); padding: 5px 6px 6px; display: flex; flex-direction: column; gap: 3px; margin-block-start: auto; }
.jr-mt__kr { display: flex; gap: 3.5px; }
.jr-mt__k { flex: 1 1 0; display: block; block-size: 7px; border-radius: 3px; background: var(--mu-n200); animation: jr-mt-key 5.6s linear infinite; }
.jr-mt__k--s { flex: none; inline-size: 14px; }
.jr-mt__k--space { flex: none; inline-size: 18px; background: var(--mu-a200); animation: none; }
@keyframes jr-mt-a { 0% { width: 0 } 20% { width: 52px } 88% { width: 52px } 100% { width: 0 } }
@keyframes jr-mt-b { 0%, 22% { width: 0 } 44% { width: 38px } 88% { width: 38px } 100% { width: 0 } }
@keyframes jr-mt-price { 0%, 46% { opacity: 0; transform: translateY(3px) } 56% { opacity: 1; transform: translateY(0) } 92% { opacity: 1; transform: translateY(0) } 100% { opacity: 0 } }
@keyframes jr-mt-caret { 0%, 100% { opacity: 1 } 50% { opacity: 0 } }
@keyframes jr-mt-key {
  0% { background: var(--mu-n200); transform: translateY(0) }
  4% { background: var(--mu-a300); transform: translateY(1.5px) }
  12% { background: var(--mu-n200); transform: translateY(0) }
  100% { background: var(--mu-n200); transform: translateY(0) }
}

/* ⭐ Bewegung ist Dekoration (README): ohne Bewegung steht jede Phase auf ihrem
   ersten Bild — beschriebenes Blatt, Telefon, Blatt mit Klammern; die Tastatur
   ruht. Nichts an der Mechanik hängt an einer Animation. */
@media (prefers-reduced-motion: reduce) {
  .jr-ps *, .jr-mt * { animation: none !important; }
  .jr-ps__ln--a { inline-size: 34px; } .jr-ps__ln--b { inline-size: 26px; } .jr-ps__ln--c { inline-size: 30px; }
  .jr-ps__pen { transform: translate(23px, 22px) rotate(-14deg); }
  .jr-ps__scene--a { opacity: 1; } .jr-ps__scene--b { opacity: 0; }
  .jr-ps__flash { opacity: 0; }
  .jr-ps__scan { opacity: 0; }
  .jr-mt__ln--a { inline-size: 52px; } .jr-mt__ln--b { inline-size: 38px; }
  .jr-mt__price { opacity: 1; }
  .jr-mt__caret { opacity: 1; }
}

/* ── Zähler: „Bereits hochgeladen: N" · Korb · roter Knopf ─────────────────── */
[data-jr-screen="menue_upload"] .jr-mu { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.jr-mu__row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 14px 0; border-block: 1px solid var(--mu-n200);
}
[data-jr-screen="menue_upload"] .jr-mu__count {
  display: flex; align-items: center; gap: 10px; margin: 0;
  font-family: inherit; font-weight: 600; font-size: 14px; line-height: 1.4; color: var(--mu-ink);
}
[data-jr-screen="menue_upload"] .jr-mu__n {
  display: grid; place-items: center; min-inline-size: 28px; block-size: 28px; padding: 0 9px;
  border-radius: 999px; background: var(--mu-n100);
  font-family: inherit; font-weight: 600; font-size: 14px; line-height: 1; font-variant-numeric: tabular-nums;
}
[data-jr-screen="menue_upload"] .jr-mu__empty {
  margin: 0; margin-inline-start: auto; flex: 1 1 8rem; min-inline-size: 0; text-align: end;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.5; color: var(--mu-n600);
}
.jr-mu__empty[hidden] { display: none; }
@media (min-width: 834px) {
  .jr-mu__row { gap: 14px; padding: 16px 0; }
  [data-jr-screen="menue_upload"] .jr-mu__count { font-size: 14px; gap: 14px; }
  [data-jr-screen="menue_upload"] .jr-mu__n { min-inline-size: 30px; block-size: 30px; padding: 0 10px; font-size: 15px; }
  [data-jr-screen="menue_upload"] .jr-mu__empty { margin-inline-start: 0; flex: 0 1 auto; text-align: start; font-size: 14px; }
}
@media (min-width: 1280px) {
  .jr-mu__row { gap: 16px; padding: 20px 0; }
  [data-jr-screen="menue_upload"] .jr-mu__count { font-size: 15px; gap: 16px; }
  [data-jr-screen="menue_upload"] .jr-mu__n { min-inline-size: 34px; block-size: 34px; padding: 0 11px; font-size: 16px; }
  [data-jr-screen="menue_upload"] .jr-mu__empty { font-size: 15px; }
}
/* Die Zeilen des Korbs — unverändert in der Mechanik, im Ton der Lieferung. */
[data-jr-screen="menue_upload"] .jr-mu__list { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
[data-jr-screen="menue_upload"] .jr-mu__list:empty { display: none; }
[data-jr-screen="menue_upload"] .jr-mu__item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--mu-n200); border-radius: 12px; background: #ffffff;
}
[data-jr-screen="menue_upload"] .jr-mu__name {
  flex: 1 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: inherit; font-weight: 500; font-size: 13.5px; line-height: 1.4; color: var(--mu-ink);
}
[data-jr-screen="menue_upload"] .jr-mu__drop { flex: 0 0 auto; margin: 0; display: flex; }
[data-jr-screen="menue_upload"] .jr-mu__x {
  display: grid; place-items: center; inline-size: 32px; block-size: 32px; padding: 0;
  border: 0; border-radius: 9px; background: transparent; color: var(--mu-n600); cursor: pointer;
}
[data-jr-screen="menue_upload"] .jr-mu__x svg { inline-size: 12px; block-size: 12px; }
[data-jr-screen="menue_upload"] .jr-mu__x:hover { background: var(--mu-n100); color: var(--mu-ink); }
[data-jr-screen="menue_upload"] .jr-mu__x:focus-visible { outline: 2px solid var(--jr-accent); outline-offset: 2px; }
/* 🪤🔴 `[hidden]` verliert gegen jede `display`-Regel — diese zwei Zeilen sind Pflicht. */
.jr-mu__build { display: block; margin: 0; }
.jr-mu__build[hidden] { display: none; }
.jr-mu__err { margin: 0; }
.jr-mu__err[hidden] { display: none; }

/* ── „Gut zu wissen" ───────────────────────────────────────────────────────── */
[data-jr-screen="menue_upload"] .jr-card.jr-mu-know {
  display: flex; flex-direction: column; gap: 10px;
  margin: 0; padding: 18px; border: 0; border-radius: var(--mu-r-know); background: var(--mu-n100);
}
.jr-mu-know__head { display: flex; align-items: center; gap: 8px; }
.jr-mu-know__icon { flex: none; inline-size: 17px; block-size: 17px; color: var(--jr-accent); }
[data-jr-screen="menue_upload"] .jr-mu-know .jr-card__title {
  margin: 0; font-family: inherit; font-weight: 600; font-size: 16px; line-height: 1.3; letter-spacing: -.01em; color: var(--mu-ink);
}
.jr-mu-know__body { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; }
[data-jr-screen="menue_upload"] .jr-mu-know .jr-card__text {
  margin: 0; font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.6; color: var(--mu-n800);
}
@media (min-width: 834px) {
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-know { gap: 12px; padding: 22px 24px; }
  .jr-mu-know__head { gap: 9px; }
  .jr-mu-know__icon { inline-size: 18px; block-size: 18px; }
  [data-jr-screen="menue_upload"] .jr-mu-know .jr-card__title { font-size: 17px; }
  [data-jr-screen="menue_upload"] .jr-mu-know .jr-card__text { font-size: 14px; }
  .jr-mu-know__body { gap: 12px; }
}
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-know { flex-direction: row; gap: 36px; padding: 28px 30px; }
  .jr-mu-know__head { gap: 10px; min-inline-size: 180px; align-items: center; }
  .jr-mu-know__icon { inline-size: 19px; block-size: 19px; }
  [data-jr-screen="menue_upload"] .jr-mu-know .jr-card__title { font-size: 18px; }
  [data-jr-screen="menue_upload"] .jr-mu-know .jr-card__text { font-size: 15px; }
}
/* Der eine Mandant, der die Tür noch nicht hat (`mu_hold`) — im selben ruhigen Ton. */
[data-jr-screen="menue_upload"] .jr-card.jr-mu-hold { margin: 0; border: 0; border-radius: var(--mu-r-note); background: var(--mu-n100); padding: 14px 16px; }
[data-jr-screen="menue_upload"] .jr-mu-hold .jr-card__text { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--mu-n800); }

/* ═══════════════════════════════════════════════════════════════════════════
   SPEISEKARTE · DESIGN-EINBAU · Chrome (Claude Design, 30.08.2026)
   Inhaber: «بدي التصميم مثل ما بعتلك بالمجلد و هي لقطات شاشة لكل احجام الشاشات».
   Die Karte (Radius 32/28/26, Schatten lg, Körper 46·56·52 / 34·32·40 / 24·18·28)
   und die Kopfzeile IN der Karte: [‹ ›]·„Station Speisekarte"·davor|danach·[DE].
   Auf dem Telefon: runder Zurück-Knopf, Stationsblock, Flaggenknopf, und darunter
   der Pfad „davor · Aufbau › Speisekarte › danach · Erfassung" auf grauem Band.
   ⛔ NUR DIESE STATION (`body[data-jr-station="menue_upload"]`): der Streifen wird
   dort von reise/index.php im `.jr-head` gerendert (`$navInHead`); alle anderen
   Stationen behalten Streifen und Kopf wie seit H3. ⛔ Kein Phasenband hier —
   die Lieferung zeigt keines; der Kicker „SPEISEKARTE" trägt die Orientierung.
   ═══════════════════════════════════════════════════════════════════════════ */
body.jr-page[data-jr-station="menue_upload"] .jr-shell {
  border-radius: 26px; box-shadow: 0 12px 32px rgba(45, 43, 43, .22); overflow: hidden;
  background: #ffffff;
}
body.jr-page[data-jr-station="menue_upload"] .jr-shell > .jr-body { padding: 24px 18px 28px; }
body.jr-page[data-jr-station="menue_upload"] .jr-phases { display: none; }
/* ── die Kopfzeile ── */
body.jr-page[data-jr-station="menue_upload"] .jr-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid #eae7e7;
}
body.jr-page[data-jr-station="menue_upload"] .jr-head > .jr-nav {
  display: flex; align-items: center; gap: 10px; flex: 0 1 auto; min-width: 0;
  width: auto; max-width: none; margin: 0; padding: 0;
}
body.jr-page[data-jr-station="menue_upload"] .jr-nav__pair {
  gap: 4px; padding: 0; border: 0; border-radius: 999px; background: transparent; box-shadow: none;
}
body.jr-page[data-jr-station="menue_upload"] .jr-nav__btn {
  width: 34px; height: 34px; border-radius: 999px; border: 1px solid #eae7e7; background: #ffffff;
  color: #7d7979; font-size: 18px;
}
body.jr-page[data-jr-station="menue_upload"] .jr-nav__btn:hover { background: #f8f4f4; color: #201e1d; }
body.jr-page[data-jr-station="menue_upload"] .jr-nav__btn--off { color: #d7d3d3; }
/* Telefon: nur der Zurück-Knopf (Lieferung „Mobile 390"). */
body.jr-page[data-jr-station="menue_upload"] .jr-nav__pair > :nth-child(2) { display: none; }
body.jr-page[data-jr-station="menue_upload"] .jr-nav__where { gap: 0; line-height: 1.2; }
body.jr-page[data-jr-station="menue_upload"] .jr-nav__path { font-size: 10px; font-weight: 400; letter-spacing: .14em; color: #9b9797; }
body.jr-page[data-jr-station="menue_upload"] .jr-nav__title { gap: 6px; }
body.jr-page[data-jr-station="menue_upload"] .jr-nav__name { font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: #201e1d; }
body.jr-page[data-jr-station="menue_upload"] .jr-nav__icon { inline-size: 14px; block-size: 14px; color: var(--jr-accent); }
/* Sprachknopf: Pille mit Flagge, Kürzel, Winkel. */
body.jr-page[data-jr-station="menue_upload"] .jr-head > .jr-langmenu { margin-inline-start: auto; flex: 0 0 auto; }
body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__toggle {
  height: auto; gap: 6px; padding: 5px 10px 5px 6px; border-radius: 999px; border: 1px solid #eae7e7;
  font-family: inherit; font-size: 12px; font-weight: 500; color: #201e1d;
}
body.jr-page[dir="rtl"][data-jr-station="menue_upload"] .jr-langmenu__toggle { padding: 5px 6px 5px 10px; }
body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__toggle:hover { border-color: #bab6b6; }
body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__code { font-family: inherit; font-size: 12px; font-weight: 500; }
body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__flag { width: 18px; height: 18px; }
body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__chevron { display: none; }
/* Der Pfad unter der Kopfzeile (Telefon). */
body.jr-page[data-jr-station="menue_upload"] .jr-head__mid {
  order: 10; flex: 1 0 100%; min-width: 0; text-align: start;
  margin: 14px -16px -14px; padding: 10px 16px; background: #f8f4f4;
}
body.jr-page[data-jr-station="menue_upload"] .jr-neighbours {
  display: flex; align-items: center; justify-content: flex-start; flex-wrap: wrap; gap: 4px 8px;
  font-family: inherit; font-size: 12px; line-height: 1.3; color: #7d7979;
}
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour { flex-direction: row; align-items: center; gap: 4px; }
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour + .jr-neighbour { border: 0; margin: 0; padding: 0; }
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__label { font-size: 12px; font-weight: 400; line-height: 1.3; color: #9b9797; }
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__label::after { content: " ·"; }
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__value { font-size: 12px; font-weight: 400; line-height: 1.3; color: #7d7979; }
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour--now { display: flex; }
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour--now .jr-neighbour__value { font-weight: 600; color: #201e1d; }
/* Winkel zwischen den drei Gliedern — ein Bidi-gespiegeltes Zeichen, also auch auf Arabisch richtig. */
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour--now::before,
body.jr-page[data-jr-station="menue_upload"] .jr-neighbour--now + .jr-neighbour::before {
  content: "\203A"; color: #bab6b6; font-size: 14px; line-height: 1; margin-inline-end: 4px;
}
@media (min-width: 560px) {
  /* Tablet (Lieferung „iPad 834"): Pille mit beiden Pfeilen, Nachbarn als eine Zeile. */
  body.jr-page[data-jr-station="menue_upload"] .jr-shell { border-radius: 28px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head { flex-wrap: nowrap; gap: 14px; padding: 16px 24px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head > .jr-nav { gap: 14px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__pair { padding: 3px; border: 1px solid #eae7e7; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__pair > :nth-child(2) { display: inline-flex; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__btn { width: 30px; height: 30px; border: 0; background: transparent; color: #9b9797; font-size: 17px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__btn:hover { background: #f8f4f4; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__name { font-size: 16px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__icon { inline-size: 15px; block-size: 15px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head__mid {
    order: 0; flex: 1 1 auto; margin: 0; padding: 0; background: transparent;
    display: flex; justify-content: flex-end;
  }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbours { gap: 16px; font-size: 13px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__label, body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__value { font-size: 13px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour--now { display: none; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour--now + .jr-neighbour::before { content: none; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head > .jr-langmenu { margin-inline-start: 0; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__toggle { gap: 8px; padding: 6px 12px 6px 7px; font-size: 13px; }
  body.jr-page[dir="rtl"][data-jr-station="menue_upload"] .jr-langmenu__toggle { padding: 6px 7px 6px 12px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__code { font-size: 13px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__flag { width: 20px; height: 20px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__chevron { display: inline-flex; }
}
@media (min-width: 834px) {
  body.jr-page[data-jr-station="menue_upload"] .jr-shell > .jr-body { padding: 34px 32px 40px; }
}
@media (min-width: 1280px) {
  /* Desktop (Lieferung „Desktop 1440"): davor/danach als zwei Ränge mit Trennstrich. */
  body.jr-page[data-jr-station="menue_upload"] .jr-shell { border-radius: 32px; }
  /* ⚖️ Inhaber 30.08.2026: «على سطح المكتب خلي الحاوية اعرض شوي» — die Karte ist auf
     dieser Station breiter als die 1120 px der Reise; «كمان اعرض حبتين» (zweiter
     Zuruf) ⇒ 1360 px — auf 1440 bleiben 40 px Rand je Seite, wie die Lieferung es
     zeigt; der Rechtsfuß darunter folgt ihr, damit die Kanten fluchten. */
  /* «كمان اكثر بحيث نوصل انه ما يصير سكرولينغ» (dritter Zuruf): die Karte wächst mit
     dem Schirm (bis 1760 px, 48 px Rand je Seite), und der Vertikal-Haushalt wird
     unten je Bildschirmhöhe gestrafft, bis die ganze Station ohne Rollbalken steht. */
  body.jr-page[data-jr-station="menue_upload"] .jr-shell--wide { max-width: min(1760px, calc(100vw - 96px)); }
  body.jr-page[data-jr-station="menue_upload"] .jr-legal { max-width: min(1760px, calc(100vw - 96px)); }
}
/* ── Ohne Rollbalken auf dem Schreibtisch ─────────────────────────────────────
   Der Inhaber sieht die Station auf 2560×1229 (Live-Protokoll 29.08.2026); die
   Lieferung stapelt Kopf, Hinweis, zwei Karten, Zähler und „Gut zu wissen" zu
   ≈1250 px. Ab 1280 px Breite und bis 1300 px Höhe wird jede Stufe der Lieferung
   um ein Drittel gestrafft (Ränder, Abstände, Bildhöhe, Schriftgrade) — die
   Ordnung, die Farben und die Formen bleiben; nur die Luft wird knapper. Eine
   zweite, engere Stufe bis 1000 px Höhe für Laptops. ⛔ Nur diese Station. */
/* ⚖️ MU-4 · 30.08.2026 — DAS `max-height: 1300px` IST WEG. Es war der Grund,
   warum der GRÖSSERE Schirm (1317 px hoch) in das ungestauchte Grundblatt
   fiel, dessen Rest 1121 px hoch ist — und dann rollte. Jetzt gilt diese
   Stufe nach oben offen, und die engere darunter überschreibt sie. */
@media (min-width: 1280px) {
  body.jr-page[data-jr-station="menue_upload"] .jr-shell { margin-block: 12px 16px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head { padding: 14px 40px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-shell > .jr-body { padding: 28px 56px 28px; }
  [data-jr-screen="menue_upload"] { --mu-gap: 20px; }
  .jr-mu-hero { gap: 8px; }
  [data-jr-screen="menue_upload"] .jr-h1.jr-mu-hero__t { font-size: 44px; }
  [data-jr-screen="menue_upload"] .jr-lede.jr-mu-hero__lede { font-size: 17px; }
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-note { padding: 12px 18px; }
  [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card, [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card--rec { padding: 24px 28px 22px; gap: 14px; }
  /* MU-4: Bildhöhe und Maßstab stehen nicht mehr hier — sie kommen aus `--mu-k`. */
  [data-jr-screen="menue_upload"] .jr-choice__label.jr-mu-card__t { font-size: 22px; }
  [data-jr-screen="menue_upload"] .jr-choice__hint.jr-mu-card__p { font-size: 14px; line-height: 1.5; }
  .jr-mu-card__cta { padding: 12px 22px; }
  .jr-mu-card__cta--secondary { padding: 11px 21px; }
  .jr-mu__row { padding: 12px 0; }
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-know { padding: 18px 24px; gap: 24px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-legal { margin-block-start: 8px; }
}
/* Ab 1280 px: der rote Knopf steht IN der Zählerzeile (zweite Rasterspalte) und die
   Korbzeilen werden umbrechende Chips — so wächst die Seite mit jeder Datei nicht
   mehr um eine Zeile, und „ohne Rollbalken" gilt auch mit gefülltem Korb. */
@media (min-width: 1280px) {
  [data-jr-screen="menue_upload"] { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 24px; align-items: start; }
  [data-jr-screen="menue_upload"] > * { grid-column: 1 / -1; }
  [data-jr-screen="menue_upload"] > .jr-mu { grid-column: 1; }
  /* ⚖️ MU-5 · 30.08.2026 · INHABER: «هذا الزر تبع ركب خليه على مستوى بلوك اسماء
     الصور المرفوعة» — der rote Knopf stand in der MITTE des ganzen Korbs, also
     zwischen der Zählerzeile und den Dateinamen. Er steht jetzt auf der Zeile
     der Namen: unten bündig mit dem Korb, dessen letzte Zeile sie sind. */
  [data-jr-screen="menue_upload"] > .jr-mu__build { grid-column: 2; align-self: end; margin: 0; }
  [data-jr-screen="menue_upload"] > .jr-mu__build .jr-cta { width: auto; min-height: 50px; padding: 0 24px; white-space: nowrap; }
  [data-jr-screen="menue_upload"] .jr-mu__list { flex-direction: row; flex-wrap: wrap; gap: 8px; }
  [data-jr-screen="menue_upload"] .jr-mu__item { padding: 5px 6px 5px 12px; border-radius: 999px; gap: 6px; }
  [data-jr-screen="menue_upload"] .jr-mu__name { flex: 0 1 auto; max-inline-size: 26ch; }
  [data-jr-screen="menue_upload"] .jr-mu__x { inline-size: 28px; block-size: 28px; border-radius: 999px; }
}
/* ⚖️ MU-4 · 30.08.2026 — 1000 ⟶ 1182 px. Die enge Stufe hat den KLEINEREN Rest
   (792 px statt 882 px auf breiten Schirmen), also bleibt dort MEHR Luft für
   das Bild. Sie reicht jetzt genau so weit hinauf, bis die weite Stufe dasselbe
   Bild trägt (Rest 882 + 8 + 173×1,64 = 1174 px) — deshalb wird das Bild an der
   Grenze nie wieder kleiner, was genau die Klage von heute war. */
@media (min-width: 1280px) and (max-height: 1182px) {
  body.jr-page[data-jr-station="menue_upload"] .jr-shell { margin-block: 6px 6px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head { padding: 8px 40px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-shell > .jr-body { padding: 12px 48px 12px; }
  [data-jr-screen="menue_upload"] { --mu-gap: 11px; }
  .jr-mu-hero { gap: 4px; }
  [data-jr-screen="menue_upload"] .jr-h1.jr-mu-hero__t { font-size: 36px; }
  [data-jr-screen="menue_upload"] .jr-lede.jr-mu-hero__lede { font-size: 15px; }
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-note { padding: 10px 16px; }
  [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card, [data-jr-screen="menue_upload"] .jr-choice.jr-mu-card--rec { padding: 18px 24px 18px; gap: 10px; }
  /* MU-4: Bildhöhe und Maßstab stehen nicht mehr hier — sie kommen aus `--mu-k`. */
  [data-jr-screen="menue_upload"] .jr-choice__label.jr-mu-card__t { font-size: 20px; }
  [data-jr-screen="menue_upload"] .jr-choice__hint.jr-mu-card__p { font-size: 13.5px; line-height: 1.45; }
  .jr-mu-card__cta { padding: 10px 20px; font-size: 14px; }
  .jr-mu-card__cta--secondary { padding: 9px 19px; }
  .jr-mu__row { padding: 9px 0; }
  [data-jr-screen="menue_upload"] .jr-card.jr-mu-know { padding: 12px 20px; gap: 20px; }
  [data-jr-screen="menue_upload"] .jr-mu-know .jr-card__text { font-size: 13.5px; line-height: 1.45; }
  body.jr-page[data-jr-station="menue_upload"] .jr-legal { margin-block-start: 4px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-shell > .jr-body { padding: 46px 56px 52px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head { gap: 18px; padding: 20px 40px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head > .jr-nav { gap: 18px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__pair { padding: 4px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__btn { width: 32px; height: 32px; font-size: 18px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__path { font-size: 11px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__title { gap: 8px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__name { font-size: 18px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-nav__icon { inline-size: 16px; block-size: 16px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbours { gap: 24px; align-items: center; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour { flex-direction: column; align-items: flex-end; gap: 1px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour + .jr-neighbour { align-items: flex-start; border-inline-start: 1px solid #eae7e7; padding-inline-start: 24px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__label { font-size: 11px; letter-spacing: .1em; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__label::after { content: none; }
  body.jr-page[data-jr-station="menue_upload"] .jr-neighbour__value { font-size: 14px; font-weight: 500; color: #605d5d; }
  body.jr-page[data-jr-station="menue_upload"] .jr-head > .jr-langmenu { margin-inline-start: 8px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__toggle { gap: 10px; padding: 7px 14px 7px 8px; font-size: 14px; }
  body.jr-page[dir="rtl"][data-jr-station="menue_upload"] .jr-langmenu__toggle { padding: 7px 8px 7px 14px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__code { font-size: 14px; }
  body.jr-page[data-jr-station="menue_upload"] .jr-langmenu__flag { width: 22px; height: 22px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   ⚖️ 30.08.2026 · OWNER — DAS BESTÄTIGUNGSFENSTER NACH EINER ÄNDERUNG SIEHT AUS
   WIE DER ERSTE BESTÄTIGUNGSSCHIRM
   ══════════════════════════════════════════════════════════════════════════
   «نافذة التأكيد يلي بتظهر اذا غير المستخدم بيانات … لازم يكون شكلها مثل نافذة
   التأكيد الأولى تبع الادخال الاول».
   Dieselben Klassen wie includes/lp_entry/pending_view.php (`.jr-h1` · `.jr-lede`
   · `.jr-vform` · `.jr-vcode` · `.jr-fine` · roter `.jr-cta`), am Anfang
   ausgerichtet wie die Karte, die es nachahmt. Die alten Fenster-Regeln (`__t`,
   `__val`, `__say`) bleiben für die Abstände; Schrift und Farbe tragen die
   geerbten Klassen. */
.jr-vdialog--first .jr-vdialog__panel { text-align: start; padding: 28px 24px 22px; }
.jr-vdialog--first .jr-vdialog__t { margin: 0 0 6px; font-size: 26px; line-height: 1.2; color: var(--jr-ink); }
.jr-vdialog--first .jr-vdialog__say { margin: 0 0 8px; font-size: 15px; color: var(--jr-muted); }
.jr-vdialog--first .jr-vdialog__val { margin: 0 0 14px; font-size: 15px; font-weight: 400; color: var(--jr-muted); }
.jr-vdialog--first .jr-vdialog__val strong { color: var(--jr-ink); font-weight: 700; }
.jr-vdialog--first .jr-vrow__again { justify-content: flex-start; }
.jr-vdialog--first .jr-vdialog__form .jr-vcode { text-align: center; }
.jr-vdialog__go { inline-size: 100%; margin-block-start: 4px; }
.jr-vdialog--first .jr-fine { margin: 12px 0 0; }
.jr-vdialog--first .jr-vdialog__close { display: block; text-align: center; }

/* ══════════════════════════════════════════════════════════════════════════
   🔴 30.08.2026 · OWNER — «الايميل تغيير بدون ما يتم تأكيده»
   ══════════════════════════════════════════════════════════════════════════
   Die Prüfen-Seite zeigt einen geänderten, noch unbestätigten Kontakt mit dem
   Wort, das die Bestätigungsliste dafür hat (`vf_open`) — als Chip neben dem
   Wert, damit „gespeichert" nicht wie „bestätigt" aussieht. */
.jr-kv__state {
  display: inline-block; margin-inline-start: 8px; padding: 1px 8px;
  border-radius: 999px; font-family: inherit; font-weight: 700; font-size: 11.5px;
  line-height: 1.6; letter-spacing: .02em; vertical-align: middle;
}
.jr-kv__state--open { background: var(--jr-amber-soft); color: var(--jr-amber-ink); border: 1px solid var(--jr-amber-line); }

/* ══════════════════════════════════════════════════════════════════════════
   MU-6 · 30.08.2026 · DIE ZWEI ERGEBNIS-ANSICHTEN DESSELBEN FENSTERS
   ══════════════════════════════════════════════════════════════════════════
   Lieferung: Claude Design, `C:\tmp\design_handoff_result_dialogs2` (README =
   die Werte · `DialogErgebnis.dc.html` · `SuccessMenu.dc.html`). Hohe Werktreue:
   Farben, Schrift, Abstände, Radien, Schatten und Zeiten stehen so, wie sie
   geliefert wurden.

   ⭐ EIN FENSTER, DREI ANSICHTEN. Die Lieferung verlangt es wörtlich: «success
   state replaces the processing content in the SAME modal (no new modal, no page
   jump)». Also erbt alles hier die Hülle von `.jr-mu-go` — Schleier, Karte,
   Eintritt, Fokusring — und nur der Inhalt wechselt.

   ⛔ SICHTBARKEIT ÜBER `[hidden]`, ABER NIE MIT `display` IN DERSELBEN REGEL.
   `[hidden]` ist ein Attribut und verliert gegen jedes `display` gleicher
   Spezifität — die Lehre, die `.jr-mu__build[hidden]` in diesem Blatt schon
   einmal aufgeschrieben hat. Deshalb: verstecken auf dem Attributselektor,
   zeigen auf `:not([hidden])`.

   ⛔ UND DAS GRÜN IST BEDEUTUNG, KEIN ANSTRICH. Die Lieferung schreibt es als
   Regel auf: «Success green (new, semantic only — not for chrome or actions)».
   Es lebt ausschließlich in `.jr-sm*` — dem Siegel — und ist deshalb auf
   `.jr-rs--ok` verwahrt statt in `:root`: von dort könnte es nie versehentlich
   in einen Knopf, einen Rahmen oder eine Schrift geraten. Die Knöpfe dieses
   Fensters tragen dasselbe Rot wie jeder andere Knopf der Reise.
   ⛔ ES IST AUCH KEIN ZWEITES `--jr-green`. Das Reise-Grün (#12b76a) ist die
   Farbe eines ZUSTANDS in der Oberfläche; dies ist die Farbe eines SIEGELS in
   einer gelieferten Zeichnung, mit vier abgestuften Tönen, die nur zueinander
   passen müssen. Zwei Rollen, zwei Paletten, keine davon im Chrome.

   ⛔ FLACHE MEDIENABFRAGEN, LOGISCHE ACHSEN (inline/block, start/end) — Arabisch
   spiegelt sich von selbst. Die Zeichnung des Siegels ist ein BILD und wird
   nicht gelesen: sie steht auf `direction: ltr` und sieht in jeder Leserichtung
   gleich aus.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── die drei Ansichten ─────────────────────────────────────────────────────── */
[data-jr-menu-view] { display: none; }
/* ⭐ `contents` und nicht `flex`: so bleiben Körper und Fuß der Arbeits-Ansicht
   die DIREKTEN Flex-Kinder der Karte, die sie vor dieser Charge waren — das
   Wartefenster aus MU-3 sieht auf den Pixel genauso aus wie gestern. */
[data-jr-menu-view="work"]:not([hidden]) { display: contents; }
.jr-rs:not([hidden]) { display: flex; flex-direction: column; }
/* ⚖️ Nur die Verwandlung wird bewegt, die Deckkraft bleibt 1 — damit ein
   eingefrorenes Bild (Bildschirmfoto, Prüfsonde) die Ansicht zeigt. */
.jr-rs:not([hidden]) { animation: jr-rs-in .42s cubic-bezier(.2, .8, .25, 1); }
@keyframes jr-rs-in { from { transform: translateY(10px) scale(.99) } to { transform: none } }

/* ⚖️ Die Fehlerkarte ist schmaler als die Erfolgskarte (520 gegen 560) — aber
   erst auf dem Schreibtisch: darunter sind beide so breit wie das Fenster. */

/* ⛔ Die Tür zur Speisekarte ist ein Formular ohne eigenes Aussehen: sie steht
   NEBEN dem anderen Formular, weil zwei ineinander kein HTML sind, und ihr Knopf
   gehört ihr über `form="mu-rev-form"` an. */
.jr-rs__door { display: none; }

/* ── Erfolg · Körper ────────────────────────────────────────────────────────── */
.jr-rs__body {
  display: flex; flex-direction: column; gap: 15px;
  padding: 20px 18px 0;
}
.jr-rs__head { display: flex; flex-direction: column; gap: 6px; }
.jr-rs__kicker {
  display: flex; align-items: center; gap: 8px;
  margin: 0;
  font-family: inherit; font-weight: 600; font-size: 10px; line-height: 1.2;
  letter-spacing: .18em;
  color: var(--mu-a700, #ae1800);
}
.jr-rs__dot {
  inline-size: 6px; block-size: 6px; flex: none;
  border-radius: 999px;
  background: var(--jr-accent, #ec3013);
}
.jr-rs__t {
  margin: 0;
  font-family: inherit; font-weight: 600; font-size: 22px; line-height: 1.2;
  letter-spacing: -.015em;
  color: var(--mu-ink, #201e1d);
}

/* ── Erfolg · der Zählerstreifen ────────────────────────────────────────────── */
/* ⛔ ZWEI ZELLEN, NICHT DREI. Die Lieferung zeichnet «Kategorien · Gerichte ·
   mit Allergenen» und schreibt für genau diesen Fall die Regel auf: «if a value
   is unknown, hide that cell rather than showing 0». Der Mandant zählt zwei
   Dinge; die dritte Zahl wird nicht erfunden. Der Streifen teilt sich deshalb
   in zwei gleiche Hälften statt in drei Drittel. */
.jr-rs__strip {
  display: flex;
  overflow: hidden;
  border: 1px solid var(--mu-n200, #eae7e7);
  border-radius: 14px;
}
.jr-rs__cell {
  flex: 1 1 0;
  display: flex; flex-direction: column; gap: 1px;
  padding: 10px 11px;
  border-inline-end: 1px solid var(--mu-n200, #eae7e7);
}
.jr-rs__cell:last-child { border-inline-end: 0; }
.jr-rs__n {
  font-family: inherit; font-weight: 600; font-size: 17px; line-height: 1.1;
  color: var(--mu-ink, #201e1d);
  /* 🪤 Zahlen bleiben Zahlen: nie arabisch-indisch, in keiner Leserichtung. */
  font-variant-numeric: lining-nums tabular-nums;
}
.jr-rs__lab {
  font-family: inherit; font-weight: 400; font-size: 10.5px; line-height: 1.35;
  color: var(--mu-n600, #7d7979);
}

/* ── Erfolg · Fuß: Hinweis, Häkchen, zwei Knöpfe ────────────────────────────── */
.jr-rs__foot {
  display: flex; flex-direction: column; gap: 9px;
  padding: 18px;
}
/* ══════════════════════════════════════════════════════════════════════════
   OW-5 · 31.08.2026 · OWNER — «شكل الشيك بوكس و موضوعه كتصميم مقرف»
   ══════════════════════════════════════════════════════════════════════════
   Hinweis und Häkchen liegen in EINER getönten Fläche — derselben, die auf
   dieser Station schon `.jr-mu-ask__tip` trägt (`--mu-a100`, Radius 14). Der
   Satz, der zur Kenntnis genommen wird, und die Kenntnisnahme sind damit
   sichtbar ein Ding statt zweier loser Zeilen zwischen Karte und Knopf. */
.jr-rs__ackbox {
  display: flex; flex-direction: column; gap: 10px;
  padding: 13px 14px;
  border-radius: 14px;
  background: var(--mu-a100, #fff2ef);
}
.jr-rs__ack {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  margin: 0; padding: 0;
  cursor: pointer;
}
/* ⛔ DAS ECHTE `<input>` BLEIBT — es ist das Feld, das abgeschickt wird, das
   der Screenreader ansagt und das die Leertaste umschaltet. Es wird nur nicht
   mehr GEZEICHNET: `opacity: 0` statt `display: none`, sonst nähme es keinen
   Fokus mehr und `autofocus` liefe ins Leere. Es liegt exakt über seinem
   gezeichneten Kästchen, damit ein Klick beide trifft. */
.jr-rs__ackin {
  position: absolute;
  inline-size: 20px; block-size: 20px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.jr-rs__ackbx {
  position: relative;
  flex: none;
  inline-size: 20px; block-size: 20px;
  border: 1.5px solid var(--mu-n400, #bab6b6);
  border-radius: 6px;
  background: #ffffff;
  transition: background-color .12s ease, border-color .12s ease;
}
/* ⛔ DER HAKEN IST ZWEI RÄNDER UND EINE DREHUNG, kein Zeichen und kein Bild:
   ein `✓` als Text wäre eine Glyphe, die je nach Schrift woanders sitzt, und
   ein SVG hier wäre ein Kind, das kein Schreiber anfasst — beides teurer als
   diese vier Zeilen. Eine Drehung um 45° kennt keine Leserichtung, also
   braucht Arabisch dafür nichts. */
.jr-rs__ackbx::after {
  content: "";
  position: absolute;
  inset-block-start: 2px; inset-inline-start: 6px;
  inline-size: 5px; block-size: 10px;
  border: solid #ffffff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0;
}
.jr-rs__ackin:checked + .jr-rs__ackbx {
  background: var(--jr-accent, #ec3013);
  border-color: var(--jr-accent, #ec3013);
}
.jr-rs__ackin:checked + .jr-rs__ackbx::after { opacity: 1; }
.jr-rs__ack:hover .jr-rs__ackbx { border-color: var(--jr-accent, #ec3013); }
/* ⚖️ DER RING SITZT AUF DEM GEZEICHNETEN KÄSTCHEN, nicht auf einem unsichtbaren
   Feld — und nur bei `:focus-visible`, damit `autofocus` beim Öffnen des
   Fensters nicht wieder den orangen Kasten malt, den der Inhaber gemeldet hat. */
.jr-rs__ackin:focus-visible + .jr-rs__ackbx {
  outline: 2px solid var(--jr-accent, #ec3013);
  outline-offset: 2px;
}
.jr-rs__note {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0; padding: 0;
  font-family: inherit; font-weight: 400; font-size: 12px; line-height: 1.55;
  color: #2d2b2b;
}
.jr-rs__warn {
  inline-size: 14px; block-size: 14px; flex: none;
  margin-block-start: 2px;
  color: var(--jr-accent, #ec3013);
}
.jr-rs__acklab {
  font-family: inherit; font-weight: 600; font-size: 12.5px; line-height: 1.4;
  color: var(--mu-ink, #201e1d);
}
.jr-rs__err { margin: 0; font-size: 12.5px; }

.jr-rs__cta {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  inline-size: 100%; min-block-size: 58px;
  padding: 8px 18px;
  border: 0; border-radius: 999px;
  background: var(--jr-accent, #ec3013);
  color: #ffffff;
  font: inherit;
  cursor: pointer;
  box-shadow: var(--mu-shadow-sm, 0 1px 2px rgba(45, 43, 43, .14));
}
.jr-rs__cta:hover { background: var(--mu-a600, #dd2b0f); }
.jr-rs__cta:active { background: var(--mu-a700, #ae1800); }
/* ⛔ EIN GESPERRTER KNOPF SIEHT GESPERRT AUS. Der Eigentümer hat verlangt, dass
   «Weiter» erst nach dem Häkchen geht (30.08.2026); ein Knopf, der voll aussieht
   und nichts tut, wäre die schlechtere Hälfte dieser Zusage. */
.jr-rs__cta[disabled] { opacity: .45; cursor: not-allowed; box-shadow: none; }
.jr-rs__cta[disabled]:hover { background: var(--jr-accent, #ec3013); }
.jr-rs__cta1 { font-size: 15px; font-weight: 600; white-space: nowrap; }
.jr-rs__cta2 { font-size: 11px; font-weight: 400; opacity: .85; white-space: nowrap; }
.jr-rs__quiet {
  display: flex; align-items: center; justify-content: center;
  inline-size: 100%; min-block-size: 50px;
  padding: 8px 18px;
  border: 1px solid var(--mu-n300, #d7d3d3); border-radius: 999px;
  background: #ffffff;
  color: var(--mu-ink, #201e1d);
  font: inherit; font-size: 15px; font-weight: 600; white-space: nowrap;
  cursor: pointer;
}
.jr-rs__quiet:hover { background: var(--mu-n100, #f8f4f4); }

/* ── Fehler ─────────────────────────────────────────────────────────────────── */
.jr-rs--bad .jr-rs__body { gap: 14px; }
.jr-rs__badhead { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.jr-rs__seal {
  display: grid; place-items: center;
  inline-size: 44px; block-size: 44px; flex: none;
  border-radius: 999px;
  background: var(--mu-a100, #fff2ef);
  color: var(--jr-accent, #ec3013);
}
.jr-rs__seal > svg { inline-size: 22px; block-size: 22px; }
.jr-rs__badtx { display: flex; flex-direction: column; gap: 6px; min-inline-size: 0; }
.jr-rs__kicker--bad { display: block; }
.jr-rs__t--bad { font-size: 21px; line-height: 1.22; }
.jr-rs__s {
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.6;
  color: var(--mu-n700, #605d5d);
}
.jr-rs__files {
  display: flex; align-items: center; gap: 10px;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--mu-n200, #eae7e7); border-radius: 14px;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.4;
  color: var(--mu-n700, #605d5d);
}
.jr-rs__tile {
  display: grid; place-items: center;
  inline-size: 32px; block-size: 32px; flex: none;
  border-radius: 8px;
  background: var(--mu-n100, #f8f4f4);
  color: var(--mu-n600, #7d7979);
}
.jr-rs__tile > svg { inline-size: 16px; block-size: 16px; }
.jr-rs__fn {
  font-weight: 600;
  font-variant-numeric: lining-nums tabular-nums;
}
.jr-rs--bad .jr-rs__foot { padding: 18px; gap: 9px; }
.jr-rs__cta--bad {
  flex-direction: row; gap: 9px;
  min-block-size: 52px;
  font-size: 15px; font-weight: 600; white-space: nowrap;
}
.jr-rs__ico { inline-size: 16px; block-size: 16px; flex: none; }

/* ══════════════════════════════════════════════════════════════════════════
   Das Siegel (`SuccessMenu.dc.html`) — 146 px, nur gezeichnete Formen
   ══════════════════════════════════════════════════════════════════════════ */
.jr-rs--ok {
  /* ⛔ HIER UND NIRGENDS SONST. Siehe die Begründung im Kopf dieses Abschnitts. */
  --sm-base: #0e8f4f;
  --sm-mid: #3fae74;
  --sm-light: #6cc496;
  --sm-line: #9ad4b4;
  --sm-tint: #e8f6ee;
}
.jr-sm {
  position: relative;
  display: flex; align-items: center; justify-content: center; gap: 18px;
  inline-size: 100%; block-size: 146px;
  padding: 0 18px;
  overflow: hidden;
  border-radius: 18px;
  background: linear-gradient(180deg, var(--mu-n100, #f8f4f4), var(--mu-n200, #eae7e7));
  /* ⛔ EIN BILD WIRD NICHT GELESEN: dieselbe Zeichnung in jeder Leserichtung. */
  direction: ltr;
}
.jr-sm__card {
  position: relative;
  display: flex; flex-direction: column; gap: 7px;
  inline-size: 196px; block-size: 112px; flex: none;
  padding: 12px 14px;
  overflow: hidden;
  border-radius: 12px;
  background: #ffffff;
  box-shadow: var(--mu-shadow-md, 0 3px 10px rgba(45, 43, 43, .16));
}
.jr-sm__row {
  display: flex; align-items: center; gap: 6px;
  animation: jr-sm-row .55s cubic-bezier(.2, .85, .3, 1) both;
}
.jr-sm__row:nth-child(2) { animation-delay: .07s; }
.jr-sm__row:nth-child(3) { animation-delay: .14s; }
.jr-sm__row:nth-child(4) { animation-delay: .21s; }
.jr-sm__row:nth-child(5) { animation-delay: .28s; }
.jr-sm__row:nth-child(6) { animation-delay: .35s; }
@keyframes jr-sm-row { from { transform: translateX(-10px) } to { transform: none } }
.jr-sm__cat { display: block; inline-size: 34px; block-size: 5px; border-radius: 999px; background: var(--jr-accent, #ec3013); }
.jr-sm__cat--b { inline-size: 26px; }
.jr-sm__tag { display: block; inline-size: 14px; block-size: 4px; border-radius: 999px; background: var(--mu-a200, #ffe0d9); }
.jr-sm__dish { display: block; block-size: 4px; border-radius: 999px; background: var(--mu-n400, #bab6b6); }
.jr-sm__dish--a { inline-size: 72px; }
.jr-sm__dish--b { inline-size: 60px; }
.jr-sm__dish--c { inline-size: 66px; }
.jr-sm__dish--d { inline-size: 54px; }
.jr-sm__chip {
  display: block; inline-size: 15px; block-size: 9px;
  border-radius: 3px;
  background: var(--sm-tint, #e8f6ee);
  border: 1px solid var(--sm-line, #9ad4b4);
}
.jr-sm__price { display: block; inline-size: 22px; block-size: 6px; margin-left: auto; border-radius: 2px; background: var(--mu-a200, #ffe0d9); }
.jr-sm__mask {
  position: absolute; inset-inline: 0; inset-block-end: 0; block-size: 22px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0), #ffffff);
}
.jr-sm__sheen {
  position: absolute; inset-block: -20%; inline-size: 34px; inset-inline-start: -40px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .75), rgba(255, 255, 255, 0));
  transform: skewX(-18deg);
  animation: jr-sm-sheen 4.6s cubic-bezier(.35, 0, .3, 1) 1.1s infinite;
}
@keyframes jr-sm-sheen { from { transform: translateX(0) skewX(-18deg) } to { transform: translateX(280px) skewX(-18deg) } }

.jr-sm__stage { position: relative; display: grid; place-items: center; inline-size: 88px; block-size: 96px; flex: none; }
.jr-sm__ring {
  position: absolute; inline-size: 74px; block-size: 74px;
  border: 2px solid var(--sm-base, #0e8f4f); border-radius: 999px;
  animation: jr-sm-ring 3.2s cubic-bezier(.25, 0, .35, 1) .5s infinite;
}
.jr-sm__ring--b { border-color: var(--sm-light, #6cc496); animation-delay: 2.1s; }
@keyframes jr-sm-ring { from { transform: scale(.5); opacity: .55 } to { transform: scale(1.85); opacity: 0 } }
.jr-sm__spark { position: absolute; display: block; border-radius: 999px; animation: jr-sm-spark 2.8s ease-out infinite; }
.jr-sm__spark--1 { inset-inline-start: 6px; inset-block-start: 22px; inline-size: 5px; block-size: 5px; background: var(--sm-mid, #3fae74); animation-delay: .4s; }
.jr-sm__spark--2 { inset-inline-end: 8px; inset-block-start: 16px; inline-size: 4px; block-size: 4px; background: var(--sm-base, #0e8f4f); animation-delay: 1.2s; }
.jr-sm__spark--3 { inset-inline-end: 16px; inset-block-end: 14px; inline-size: 4px; block-size: 4px; background: var(--sm-light, #6cc496); animation-delay: 2s; }
@keyframes jr-sm-spark { from { transform: translateY(0); opacity: .9 } to { transform: translateY(-14px); opacity: 0 } }

/* ⭐ Tönung UND Siegel liegen in DERSELBEN schwebenden Gruppe und tragen
   DIESELBE Stempel-Bewegung — die Lieferung verlangt es ausdrücklich, damit die
   beiden nie auseinanderlaufen. */
.jr-sm__float { position: relative; display: grid; place-items: center; animation: jr-sm-float 3.8s ease-in-out 1s infinite; }
@keyframes jr-sm-float { 0%, 100% { transform: translateY(-3.5px) } 50% { transform: translateY(3.5px) } }
.jr-sm__tint { position: absolute; inline-size: 64px; block-size: 64px; border-radius: 999px; background: var(--sm-tint, #e8f6ee); animation: jr-sm-stamp .72s cubic-bezier(.2, .9, .28, 1) both; }
.jr-sm__seal {
  position: relative; display: grid; place-items: center;
  inline-size: 52px; block-size: 52px;
  border-radius: 999px;
  background: var(--sm-base, #0e8f4f);
  box-shadow: 0 6px 18px rgba(14, 143, 79, .34);
  animation: jr-sm-stamp .72s cubic-bezier(.2, .9, .28, 1) both;
}
.jr-sm__seal > svg { inline-size: 28px; block-size: 28px; }
@keyframes jr-sm-stamp {
  0% { transform: scale(.55) rotate(-12deg) }
  60% { transform: scale(1.1) rotate(3deg) }
  100% { transform: none }
}
/* ⛔ `stroke-dashoffset: 0` STEHT IM MARKUP, nicht nur hier: so ist der Haken
   auch dann gezeichnet, wenn die Bewegung nie läuft (Bildschirmfoto, Sonde,
   `prefers-reduced-motion`). Die Bewegung nimmt ihn nur kurz weg. */
.jr-sm__draw { animation: jr-sm-draw .6s cubic-bezier(.4, 0, .3, 1) .3s forwards; }
@keyframes jr-sm-draw { from { stroke-dashoffset: 34 } to { stroke-dashoffset: 0 } }
.jr-sm__badge {
  position: absolute; inset-inline-end: -6px; inset-block-end: -2px;
  display: grid; place-items: center;
  inline-size: 24px; block-size: 24px;
  border-radius: 999px;
  background: #ffffff;
  box-shadow: var(--mu-shadow-sm, 0 1px 2px rgba(45, 43, 43, .14));
  animation: jr-sm-badge .5s cubic-bezier(.2, .9, .3, 1) .62s both;
}
.jr-sm__badge > svg { inline-size: 14px; block-size: 14px; }
@keyframes jr-sm-badge { from { transform: scale(.4) } to { transform: none } }

/* ── Tablet ab 834 px ───────────────────────────────────────────────────────── */
@media (min-width: 834px) {
  .jr-rs__body { gap: 18px; padding: 26px 28px 0; }
  .jr-rs__head { gap: 7px; }
  .jr-rs__kicker { font-size: 10.5px; }
  .jr-rs__dot { inline-size: 7px; block-size: 7px; }
  .jr-rs__t { font-size: 25px; line-height: 1.16; letter-spacing: -.02em; }
  .jr-rs__strip { border-radius: 14px; }
  .jr-rs__cell { padding: 12px 14px; gap: 2px; }
  .jr-rs__n { font-size: 18px; }
  .jr-rs__lab { font-size: 11.5px; }
  .jr-rs__foot { gap: 9px; padding: 20px 28px 24px; }
  .jr-rs__cta { min-block-size: 56px; }
  .jr-rs__cta1 { font-size: 15px; }
  .jr-rs__quiet { min-block-size: 48px; font-size: 14.5px; }

  .jr-rs--bad .jr-rs__body { gap: 18px; }
  /* ⚖️ Ab hier steht das Warnzeichen NEBEN dem Text, nicht darüber. */
  .jr-rs__badhead { flex-direction: row; align-items: flex-start; gap: 16px; }
  .jr-rs__seal { inline-size: 48px; block-size: 48px; }
  .jr-rs__seal > svg { inline-size: 24px; block-size: 24px; }
  .jr-rs__badtx { gap: 7px; }
  .jr-rs__t--bad { font-size: 26px; line-height: 1.18; }
  .jr-rs__s { font-size: 15px; }
  .jr-rs__files { gap: 12px; padding: 12px 14px; border-radius: 16px; font-size: 14px; }
  .jr-rs__tile { inline-size: 36px; block-size: 36px; border-radius: 9px; }
  .jr-rs__tile > svg { inline-size: 18px; block-size: 18px; }
  .jr-rs--bad .jr-rs__foot { padding: 20px 28px 24px; gap: 10px; }
  .jr-rs__cta--bad { min-block-size: 54px; gap: 10px; }
  .jr-rs__ico { inline-size: 17px; block-size: 17px; }
}

/* ── Schreibtisch ab 1280 px ────────────────────────────────────────────────── */
@media (min-width: 1280px) {
  /* ⚖️ Die Erfolgskarte ist die 560 px, die `.jr-mu-go__panel` ohnehin trägt;
     nur die Fehlerkarte ist schmaler (Lieferung: 520 px). */
  .jr-mu-go[data-jr-menu-state="bad"] .jr-mu-go__panel { inline-size: 520px; }
  .jr-rs__body { gap: 20px; padding: 30px 34px 0; }
  .jr-rs__head { gap: 8px; }
  .jr-rs__kicker { font-size: 11px; }
  .jr-rs__t { font-size: 28px; }
  .jr-rs__strip { border-radius: 16px; }
  .jr-rs__cell { padding: 14px 16px; }
  .jr-rs__n { font-size: 20px; }
  .jr-rs__lab { font-size: 12px; }
  .jr-rs__foot { gap: 10px; padding: 22px 34px 26px; }
  .jr-rs__ack { gap: 9px; }
  .jr-rs__note { gap: 9px; font-size: 12px; }
  .jr-rs__warn { inline-size: 15px; block-size: 15px; }
  .jr-rs__acklab { font-size: 13px; }
  .jr-rs__cta { min-block-size: 58px; }
  .jr-rs__cta1 { font-size: 16px; }
  .jr-rs__cta2 { font-size: 11.5px; }
  .jr-rs__quiet { min-block-size: 50px; font-size: 15px; }
  .jr-rs__quiet:hover { border-color: var(--mu-n400, #bab6b6); }

  .jr-rs--bad .jr-rs__body { padding: 30px 34px 0; }
  .jr-rs--bad .jr-rs__foot { padding: 22px 34px 26px; }
}

/* ── ohne Bewegung ─────────────────────────────────────────────────────────────
   ⭐ Die Lieferung schreibt den Vertrag: «Under prefers-reduced-motion: reduce
   freeze at frame 0 — seal, check, tint, rows and chips all read correctly
   there.» Jede Bewegung dieses Abschnitts ist hier eingetragen, und alles, dessen
   Bild 0 außerhalb steht, bekommt seine Ruhelage. */
@media (prefers-reduced-motion: reduce) {
  .jr-rs, .jr-sm__row, .jr-sm__sheen, .jr-sm__ring, .jr-sm__spark,
  .jr-sm__float, .jr-sm__tint, .jr-sm__seal, .jr-sm__draw, .jr-sm__badge {
    animation: none !important;
  }
  /* ⛔ Ohne Lauf stünde der Glanzstreifen links außerhalb der Karte und die
     Ringe hätten ihre halbe Größe — hier stehen sie unsichtbar bzw. ruhig. */
  .jr-sm__sheen { opacity: 0; }
  .jr-sm__ring { opacity: 0; }
  .jr-sm__spark { opacity: 0; }
  .jr-sm__row, .jr-sm__float, .jr-sm__tint, .jr-sm__seal, .jr-sm__badge { transform: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   OW-1 · 31.08.2026 · OWNER — DER ERZEUGTE VORSCHLAG BEKOMMT DEN BEHÄLTER
   ══════════════════════════════════════════════════════════════════════════
   «بس يتم توليد شعار مباشرة يتم وضعه بحاوية Dieses Logo wird verwendet و النص
    يلي تحت الشعار Dieses Logo übernehmen يصير هو الزر.»

   ⭐ DERSELBE BEHÄLTER, ABSICHTLICH. Die Karte trägt `.jr-card` — Rahmen, Radius
   und Polsterung von «Dieses Logo wird verwendet» — damit auf dem Bildschirm
   zwei gleich gebaute Behälter stehen: links das Logo, das benutzt WIRD, rechts
   das erzeugte mit seinem Knopf. Ein Wechsel zwischen zwei Dingen ist nur dann
   ein Wechsel, wenn beide gleich aussehen; verschiedene Formen hätten daraus
   «ein Logo und ein Vorschau-Schnipsel» gemacht.

   ⛔ SPALTE, NICHT ZEILE — und das ist der Unterschied zu `.jr-logo-have`. Dort
   steht ein 72-px-Daumennagel neben einem Satz, weil die Auskunft der SATZ ist.
   Hier IST das Bild die Auskunft: der Betreiber entscheidet über eine Marke, die
   er zum ersten Mal sieht, und dafür muss sie groß sein. Der Knopf sitzt
   darunter, weil genau dort vorher die Bildunterschrift stand, die er ersetzt.

   ⚠️ UND DAS KARO HINTER DEM BILD IST KEINE DEKORATION. Vorschläge sind
   transparente PNG — das ist der ganze Zweck dieser Station. Auf der weißen
   Karte wäre eine weiße Marke auf Transparenz ein leeres Feld, also liegt
   dieselbe Schachbrett-Fläche dahinter, die `.jr-logo-slot__img` seit P3 trägt.
   ⛔ `object-fit: contain`, niemals `cover`: ein beschnittenes Logo ist ein
   falsches Logo (dieselbe Messung wie bei `.jr-logo-have__img`).

   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3.
   ────────────────────────────────────────────────────────────────────────── */
.jr-logo-offer {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  margin-block-start: 12px;
}
.jr-logo-offer__img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 1;
  max-block-size: 320px;
  object-fit: contain;
  border-radius: 10px;
  padding: 8px;
  background-color: var(--jr-quiet);
  background-image:
    linear-gradient(45deg, var(--jr-line-soft) 25%, transparent 25%, transparent 75%, var(--jr-line-soft) 75%),
    linear-gradient(45deg, var(--jr-line-soft) 25%, transparent 25%, transparent 75%, var(--jr-line-soft) 75%);
  background-size: 12px 12px;
  background-position: 0 0, 6px 6px;
}
/* ⛔ Volle Breite der Karte und kein `--row`: `.jr-cta--row` ist die Form für
   zwei Knöpfe NEBENEINANDER (sie stammt aus dem gelöschten Fenster). Hier steht
   einer allein unter seinem Bild und darf so breit sein wie es. */
.jr-logo-offer__cta { inline-size: 100%; }

/* ══════════════════════════════════════════════════════════════════════════
   OW-7 · 31.08.2026 · OWNER — DER ZÄHLER, DER ECHTE BALKEN UND DIE ZWEI SÄTZE
   ══════════════════════════════════════════════════════════════════════════
   «و بدنا عداد تنازلي … و اذا وصل العداد لصفر بتظهر رسالة انه في تأخير بسبب
    الضغط … و ليوصل فترة الانتظار لزمن معين منطقي معنها في خلل واضح.»
   Die Zahlen dahinter stehen in includes/journey_menu_eta.php, gemessen an
   einem echten Lauf vom 31.08. (5 Dateien, 95,3 s). Hier steht nur, wie sie
   aussehen.
   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3. */
/* 🪤🔴 GEMESSEN AM 31.08. IM ECHTEN BROWSER, UND ES WAR DIE ALTE FALLE:
   `[hidden]` VERLIERT GEGEN EIN `display` IN EINER KLASSENREGEL. Die erste
   Fassung schrieb `display: flex` hierher — und der Zähler stand von der ersten
   Sekunde an da («Voraussichtlich noch» ohne Zahl), obwohl der Server ihn
   `hidden` gezeichnet hatte. Dieselbe Lehre, die `[data-jr-menu-view]` und
   `.jr-logo-wait` schon aufgeschrieben haben.
   ⇒ BEIDE ZUSTÄNDE IN DERSELBEN EIGENSCHAFT, und das Sichtbare hängt an
   `:not([hidden])`. */
/* 🔴 OW-9 · 31.08.2026 · OWNER — DIE ZEILE WURDE ZUR ABLESUNG.
   «هي كبرلي ياها هون لازم يكون العداد كبير و احمر و الكتابة بشكل و حجم و مكان
    مناسب و انيق مع العداد.»
   Hier stand eine Zeile: Wort und Zahl nebeneinander auf einer Grundlinie, 12,5
   und 13,5 px. Sie ging unter — die Karte trägt Kicker, Titel, Absatz, ein
   146-px-Bild, den Balken und drei Schritte, und die einzige Auskunft, die man
   MEHRFACH liest, war die kleinste Schrift darin.
   ⇒ SPALTE STATT ZEILE: das Wort klein und ruhig oben, die Zahl groß darunter.
   Die Begründung jeder Zahl steht im OW-9-Block am Dateiende. */
.jr-mu-go__eta { display: none; }
.jr-mu-go__eta:not([hidden]) {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  margin: -6px 0 0;
  font-family: inherit; font-weight: 500; font-size: 13px; line-height: 1.35;
  color: var(--mu-n700, #605d5d);
}
/* 🪤 Ziffern bleiben lateinisch und tabellarisch: eine Uhr, deren Zeichen
   unterschiedlich breit sind, zappelt bei jedem Tick. Und niemals
   arabisch-indisch — stehende Regel dieser Reise. */
.jr-mu-go__clock {
  display: block;
  font-family: inherit; font-weight: 700; font-size: 34px; line-height: 1.05;
  color: var(--jr-accent, #ec3013);
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
}
.jr-mu-go__slow {
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.5;
  color: var(--mu-n700, #605d5d);
}
/* ⚖️ Der Ton ist `hold`, nicht `error`: es ist nichts kaputt, es dauert länger.
   Dieselbe Unterscheidung, die journey_view_transport_copy() für die Banner
   trifft — ein rotes Feld hier würde einen laufenden Auftrag für gescheitert
   erklären, während er noch arbeitet. */
/* 🪤 DIESELBE FALLE, DIESELBE ANTWORT — hier hätte sie den Satz «Das dauert zu
   lange» über einen Import gelegt, der gerade erst angefangen hat. Gemessen im
   Bildschirmfoto vom 31.08., nicht überlegt. */
.jr-mu-go__stuck { display: none; }
.jr-mu-go__stuck:not([hidden]) {
  display: flex; flex-direction: column; gap: 5px;
  margin: 0 18px 4px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--mu-a100, #fff2ef);
}
.jr-mu-go__stuckt {
  margin: 0;
  font-family: inherit; font-weight: 600; font-size: 13px; line-height: 1.4;
  color: var(--mu-ink, #201e1d);
}
.jr-mu-go__stucks {
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 12.5px; line-height: 1.55;
  color: var(--mu-n700, #605d5d);
}
@media (min-width: 720px) {
  .jr-mu-go__stuck:not([hidden]) { margin-inline: 28px; }
}

/* ── der Balken, sobald der Mandant eine Zahl nennt ────────────────────────── */
/* ⭐ EINE ZWEITE ERSCHEINUNG DESSELBEN ELEMENTS, kein zweites Element: solange
   `data-jr-menu-bar` leer ist, läuft die unbestimmte Animation von MU-3 weiter;
   sobald `jr-menu-photos.js` die erste gemessene Zahl vom Mandanten bekommt,
   schreibt es `live` und die Breite folgt `--jr-mu-go-pct`.
   ⛔ DIE ANIMATION WIRD ABGESCHALTET UND NICHT ÜBERSCHRIEBEN — ein Balken, der
   gleichzeitig wandert und eine Breite hat, ist ein Balken, der lügt. */
.jr-mu-go__bar[data-jr-menu-bar="live"] > span {
  position: absolute;
  inset-inline-start: 0;
  animation: none;
  inline-size: var(--jr-mu-go-pct, 0%);
  transition: inline-size .4s ease;
}

/* ══════════════════════════════════════════════════════════════════════════
   OW-8 · 31.08.2026 · OWNER — DER HINWEIS, AUF DEN DER ANGEHALTENE PFEIL ZEIGT
   ══════════════════════════════════════════════════════════════════════════
   «اذا المحطة ملزمة بأخذ بيانات لازم ما تتجاوب مع المستخدم و تعطيه تنبيه شو
    المشكلة و هذا بكل المحطات مو بس بهي المحطة.»

   ⭐ `:target` UND SONST NICHTS — kein Skript, keine Klasse, kein Zustand, den
   jemand vergessen kann zurückzusetzen. Der Pfeil ist ein Anker hierher, der
   Browser springt, die Regel zeigt.
   🪤 BEIDE ZUSTÄNDE IN DERSELBEN EIGENSCHAFT. `[hidden]` wäre hier wertlos: eine
   Klassenregel mit `display` schlägt die UA-Regel für `[hidden]` (die Lehre, die
   `[data-jr-menu-view]` aufgeschrieben hat). Also `display: none` und
   `display: block`, im selben Selektorpaar.
   ⚖️ DER TON IST `hold`, NICHT `error`: nichts ist schiefgegangen, es ist nur
   noch nicht fertig. Genau die Unterscheidung, die E2 für die Banner getroffen
   hat, mit denselben drei Farben.
   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3. */
.jr-hold { display: none; }
.jr-hold:target {
  display: block;
  margin: 0 0 18px;
  padding: 13px 15px;
  border-radius: 12px;
  border: 1px solid var(--jr-amber-line);
  background: var(--jr-amber-soft);
  color: var(--jr-amber-ink);
}
.jr-hold:target:focus-visible { outline: 2px solid var(--jr-amber); outline-offset: 2px; }
.jr-hold__t {
  margin: 0 0 4px;
  font-family: inherit; font-weight: 600; font-size: 13.5px; line-height: 1.4;
}
.jr-hold__s {
  margin: 0;
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.55;
}
/* ⛔ Die Aufzählungszeichen sitzen INNEN (`padding-inline-start`), damit sie in
   beiden Leserichtungen im Kasten bleiben statt über seinen Rand zu hängen. */
.jr-hold__list { margin: 8px 0 0; padding-inline-start: 20px; }
.jr-hold__item {
  font-family: inherit; font-weight: 400; font-size: 13px; line-height: 1.55;
}

/* ══════════════════════════════════════════════════════════════════════════
   OW-9 · 31.08.2026 · OWNER — DER ZÄHLER WIRD GROSS UND ROT
   ══════════════════════════════════════════════════════════════════════════
   «هي كبرلي ياها هون لازم يكون العداد كبير و احمر و الكتابة بشكل و حجم و مكان
    مناسب و انيق مع العداد.»

   Drei Dinge stehen in diesem Satz, und alle drei sind hier beantwortet:
   GROSS · ROT · und das Wort daneben in Form, Größe und Platz, die dazu passen.
   Die Grundregeln stehen oben beim OW-7-Block (eine Definition, nicht zwei);
   hier stehen die zwei Größenstufen und die eine Falle, die Arabisch stellt.

   ⭐ WARUM 34 PX AUF DEM TELEFON. Der Titel des Fensters ist 21 px. Eine Zahl,
   die man alle paar Sekunden sucht, muss GRÖSSER sein als die Überschrift, die
   man einmal liest — 34 px sind das 1,62-fache, also genau der Sprung, den die
   Karte sonst nirgends macht. Nach oben ist sie durch die Karte begrenzt: bei
   360 px Gerätebreite bleiben 296 px Textbreite (Fenster 14 px Polsterung,
   Rumpf 18 px), «10:00» bei 700er Ziffern ≈ 91 px. Es gibt also Luft, aber
   nicht die Aufgabe, sie zu füllen.
   ⭐ 40 UND 44 sind keine neue Idee, sondern dieselbe Verhältniszahl auf den
   Karten von 500 px (ab 834) und 560 px (ab 1280), deren Titel dort 24 und
   27 px trägt.

   ⚖️ DAS ROT IST `--jr-accent` UND KEIN ZWEITES. Es ist genau das Rot des
   Balkens zwei Zeilen darüber und des pulsenden Punktes im Kicker — die Zahl
   IST die Ablesung dieses Balkens, und ein zweiter Rotton daneben wären zwei
   Instrumente statt einem. 🔬 Kontrast auf Weiß gerechnet: #ec3013 auf #ffffff
   = 4,20:1. Für Text ab 18,66 px in Fettschrift verlangt WCAG AA 3:1 — 34 px
   in 700 liegen weit darüber. Das Wort darüber trägt deshalb NICHT dieses Rot,
   sondern `--mu-n700` (#605d5d = 6,0:1): es ist klein, und klein muss 4,5:1.

   ⛔ DAS WORT WÄCHST NUR EIN WENIG MIT (13 → 13,5 → 14 px, Gewicht 500). Der
   Inhaber wollte es «مناسب و انيق مع العداد» — passend ZUM Zähler, nicht neben
   ihm laut. Ein zweiter großer Satz hätte die Zahl wieder halbiert.
   ⛔ UND KEIN KASTEN, KEINE LINIE, KEINE FLÄCHE. `--mu-a100` ist auf dieser
   Station bereits die Fläche des Stau-Kastens und des laufenden Schritt-Punktes;
   eine dritte Bedeutung hätte beide entwertet. Die Größe trägt allein.

   🪤🔴 UND HIER IST DIE FALLE, DIE ARABISCH STELLT — GEMESSEN, NICHT VERMUTET:
   `body.jr-page[dir="rtl"] * { line-height: 1.7 }` (Z. 309) hat die Spezifität
   (0,2,1) und schlägt jede Regel, die nur eine Klasse nennt. Eine 34-px-Zahl
   bekäme dort eine 58 px hohe Zeile — zwanzig Pixel Loch unter dem Balken, und
   zwar AUSGERECHNET in der Sprache, aus der die Anweisung kam. Der Zähler holt
   sich seine Zeilenhöhe deshalb mit `:not([hidden])` in der Kette zurück
   ((0,3,0) schlägt (0,2,1)) — derselbe Griff, den `.jr-poster__t` seit D2 tut.
   ⛔ DAS WORT BEKOMMT DIESE KORREKTUR NICHT. Für arabischen Fließtext ist die
   1,7 kein Unfall, sondern der Grund, warum die Regel existiert.
   ⛔ UND KEIN `letter-spacing` AUF DER ZAHL: Z. 279 löscht es unter RTL mit
   `!important`, die zwei Leserichtungen wären dann verschieden breit.

   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3. */
.jr-mu-go__eta:not([hidden]) .jr-mu-go__clock { line-height: 1.05; }
@media (min-width: 834px) {
  .jr-mu-go__eta:not([hidden]) { gap: 3px; margin-block-start: -7px; font-size: 13.5px; }
  .jr-mu-go__eta:not([hidden]) .jr-mu-go__clock { font-size: 40px; }
}
@media (min-width: 1280px) {
  .jr-mu-go__eta:not([hidden]) { gap: 4px; margin-block-start: -8px; font-size: 14px; }
  .jr-mu-go__eta:not([hidden]) .jr-mu-go__clock { font-size: 44px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   OW-10 · 31.08.2026 · OWNER — «شوف كلمة الاثنان كيف» : DIE LEISTE BRACH DAS WORT
   ══════════════════════════════════════════════════════════════════════════
   «هون بالواجهة العربية شوف كلمة الاثنان كيف !!! و شوفها بباقي اللغات !»

   🔬 GEMESSEN AUS DEM STYLESHEET, NICHT GERATEN. Auf einem 390-px-Telefon:
   `body.jr-page` padding-inline clamp(8, 2.4vw, 24) = 9,36 je Seite (Z. 268),
   `.jr-shell` höchstens 460 (Z. 339), `.jr-body` padding-inline 20 (Z. 5186).
   Bleiben 331,28 px für `.jr-seg`; minus 2×3 Polster und 2×3 Lücke (Z. 2190)
   teilen sich DREI GLEICHE Zellen 319,28 px ⇒ 106,43 px je Zelle.

   ⛔ UND DIE DRITTE ZELLE IST DIE ÄRMSTE, OBWOHL SIE GLEICH BREIT IST — das
   ist die eigentliche Ursache, nicht der Umbruch. In jeder Zelle stehen 2×6 px
   Polster (Z. 2198), ein Icon 17 px und eine Lücke 7 px (Z. 2193/2207). Bei
   EINEM Icon bleiben 70,43 px für das Wort — bei «beide», das seit dem
   24.08.2026 ZWEI Icons trägt (form_zeiten.php, «ايقونات توصيل واستلام
   احترافية»), nur 46,43 px. «الاثنان» braucht bei 14,5 px rund 50,75 px.
   Es fehlten 4,3 px, und `overflow-wrap: anywhere` (Z. 2202) brach daraufhin
   irgendwo: sechs Zeichen passten, das siebte fiel auf die zweite Zeile.
   ⇒ Die Zelle mit dem MEISTEN Inhalt bekam den KLEINSTEN Textkasten.

   🔬 UND ARABISCH WAR NUR DER FALL, DEN DAS GERÄT DES INHABERS ZEIGT. Im
   echten Chromium gemessen (`ow10_seg_wrap_probe.js --negativ`, fünf Breiten
   mal fünf Sprachen): SIEBZEHN gebrochene Wörter in VIER Sprachen. Auf 320 px
   zerfielen de «Abholung/Lieferung/Beides», ku «Hilgirtin/Gihandin/Herdu»,
   en «Delivery/Both», tr «Teslimat» und ar «الاثنان»; de «Beides» brach noch
   auf 390 px. Der Inhaber hat also nicht einen Einzelfall gemeldet, sondern
   die eine Stelle, die sein Gerät zeigt.
   ⛔ UND «beide» IST IN JEDER SPRACHE DAS ZUERST BRECHENDE FELD — weil sein
   Kasten strukturell 24 px schmaler ist. Das ist der Beweis, dass die Ursache
   die Geometrie ist und nicht die Länge irgendeines Wortes.

   ⛔ `overflow-wrap: anywhere` BLEIBT STEHEN, obwohl es der Täter war. Ohne
   die Regel schrumpft eine Flex-Zelle nicht unter ihr längstes Wort: auf
   320 px brauchten die drei Zellen in Deutsch zusammen 311,4 px in einer
   258 px breiten Wanne und liefen unter `.jr-shell { overflow: clip }`
   (Z. 348) heraus — aus einem gebrochenen Wort würde ein ABGESCHNITTENES.
   Sie ist das Netz; hier wird der Grund beseitigt, dass sie greift.

   ⇒ AUF SCHMALEN SCHIRMEN STEHEN ICONS UND WORT UNTEREINANDER. Dann bekommt
   JEDE Zelle die volle Breite für ihr Wort — auf 320 px 76 px statt 24 —,
   «beide» verliert seinen 24-px-Nachteil, und das zweite Icon bleibt. Das
   längste Wort aller fünf Sprachen («Lieferung»/«Hilgirtin», ~67,9 px nach
   dem konservativen Maß) passt damit auf dem SCHMALSTEN Gerät.

   ⚠️ DIE 44 PX WERDEN NICHT ANGETASTET UND KOSTEN NICHTS — 🔬 GEMESSEN, nicht
   gerechnet. Ohne Block-Polster ist die Inhaltshöhe 17 (Zeichen) + 2 (row-gap)
   + 18,13 (Text) = 37,13 px lateinisch bzw. 43,65 px arabisch (line-height 1.7
   aus Z. 309) — beide UNTER `min-height: 44px`. Im Browser bleibt die Leiste
   in ALLEN 25 Kombinationen exakt 50 px hoch, genau wie vorher; im defekten
   Zustand trieb der Bruch sie auf 55 px (ar/320) und 60 px (de/320).

   ⛔ `flex-wrap`, NICHT `flex-direction: column`: eine Spalte würde bei
   «beide» die ZWEI Icons ÜBEREINANDER stapeln und drei Zeilen erzeugen. So
   bleiben die Icons nebeneinander (sie sind `flex: 0 0 auto`, Z. 2208) und
   nur das Wort wird auf eine eigene, volle Zeile gezwungen.
   ⛔ CONTAINER-, KEINE MEDIA-QUERY — dieselbe Lehre wie bei `.jr-gr` (Z. 1666)
   und `.jr-wkr` (Z. 2320): DIESELBE Leiste steht auf dem Telefon in 264–369 px
   Wanne und bei voller Shell in 420 px. 400 px ist die Schwelle, die diese
   Datei schon zweimal benutzt.
   ⛔ KEIN MARKUP, KEINE NEUE KLASSE, KEIN NEUER SCHLÜSSEL — der Zähler bleibt 603.

   🪤 UND KEIN GATE KONNTE DAS SEHEN: `journey_visual_gate.js` definiert
   «clipped» als `scrollWidth - clientWidth > 1`. Ein Wortumbruch erzeugt
   KEINEN Überlauf — der Kasten ist genau so breit wie erlaubt, nur höher. Die
   Leiste war für jedes vorhandene Prüfwerkzeug grün, während sie ein Wort
   zerschnitt. Deshalb misst `ow10_seg_wrap_probe.js` jetzt `getClientRects()`.

   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3. */
.jr-seg { container-type: inline-size; }
@container (max-width: 400px) {
  .jr-seg__opt { flex-wrap: wrap; align-content: center; row-gap: 2px; padding-inline: 4px; }
  /* 🪤🔴 `:not(.jr-seg__icon)` IST DER GANZE UNTERSCHIED, UND ER WURDE TEUER
     GEMESSEN. Die Icons SIND `<span>` — die erste Fassung schrieb
     `.jr-seg__opt > span { flex-basis: 100% }` und traf damit auch sie: jedes
     Zeichen bekam seine eigene Zeile, «beide» wurde dreizeilig und die Leiste
     wuchs von 50 auf 62/69 px. Im Browser gemessen (Icon-Oberkanten 19 px
     auseinander), nicht überlegt — dieselbe Klasse Fehler, die `.jr-seg__opt`
     schon in Z. 2202 trägt, wo die Breitspur nur zufällig harmlos ist. */
  .jr-seg__opt > span:not(.jr-seg__icon) { flex-basis: 100%; }
}

/* ══════════════════════════════════════════════════════════════════════════
   STARTKLAR · 01.09.2026 · OWNER — ZWEI NEUE SCHIRME AM ENDE DER REISE
   ══════════════════════════════════════════════════════════════════════════
   «رح نركب تصميم جديد كلياً … رح نخلق محطة جديدة منفصلة لموضوع التطبيق»

   Station 15 (`launch_station`) wird von einer Liste mit «Erledigt / Später»
   zu einer geführten Vorführung, die zum Werkzeugkasten wird. Station 16
   (`bestellungen_empfangen`) ist neu und trägt die App.

   ⛔ NUR DIESE ZWEI SCHIRME: alles hängt unter `.jr-sk` bzw. `.jr-be`. Die
   Töne der Lieferung (warme Neutralen ab #f8f4f4, Akzent-Rampe, #f3f2f2 als
   Grund) stehen als `--sk-*` AUF DEM ABSCHNITT — die Reise-Chrome (Streifen,
   Kopf, Fuss, Sprachmenü) behält ihre eigenen Töne, damit die anderen sechzehn
   Stationen nicht mitwandern. Dieselbe Anordnung, die `menue_upload` seit dem
   30.08.2026 benutzt (Z. 6387).

   ⛔ KEINE SCHARFEN ECKEN. Ausdrückliche Vorgabe der Lieferung; das Basis-
   Designsystem des Prototyps setzt `--radius-*: 0px` und überschreibt jede
   Ecke inline. Hier stehen die Radien als eigene Marken (`--sk-r-*`), damit
   niemand versehentlich nach `--jr-radius` greift und eckige Karten bekommt.

   🪤🔴 UND HIER SIND DIE ZWEI FALLEN, DIE ARABISCH STELLT — beide sind in
   dieser Datei schon einmal teuer bezahlt worden:
     · `body.jr-page[dir="rtl"] * { line-height: 1.7 }` (Z. 309) hat die
       Spezifität (0,2,1) und schlägt JEDE Regel, die nur eine Klasse nennt.
       Jede Zeilenhöhe, auf die es hier ankommt, holt sie sich deshalb mit
       `:not([hidden])` in der Kette zurück ((0,3,0) schlägt (0,2,1)) — derselbe
       Griff wie bei `.jr-poster__t` und `.jr-mu-go__eta`.
     · `body.jr-page[dir="rtl"] * { letter-spacing: normal !important }`
       (Z. 279) löscht jede Laufweite unter RTL. Die Kicker der Lieferung
       (`.2em`) erscheinen auf Arabisch also ohne Sperrung — das ist richtig so
       (arabische Buchstaben verbinden sich) und wird nicht bekämpft.

   ⛔ CONTAINER-, KEINE MEDIA-QUERIES für die Szenen: derselbe Schirm steht auf
   dem Telefon in einer 331-px-Wanne und bei voller Bahn in 1120 px.

   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3. */

.jr-sk,
.jr-be {
  --sk-paper: #f3f2f2;
  --sk-card: #ffffff;
  --sk-ink: #201e1d;
  --sk-n100: #f8f4f4;
  --sk-n200: #eae7e7;
  --sk-n300: #d7d3d3;
  --sk-n400: #bab6b6;
  --sk-n500: #9b9797;
  --sk-n600: #7d7979;
  --sk-n700: #605d5d;
  --sk-n800: #444141;
  --sk-n900: #2d2b2b;
  --sk-acc: #ec3013;
  --sk-acc100: #fff2ef;
  --sk-acc600: #dd2b0f;
  --sk-acc700: #ae1800;
  --sk-ok: #0e8f4f;
  --sk-ok-ink: #0b7440;
  --sk-ok-soft: #e8f6ee;
  --sk-ok-deep: #0b5c34;
  --sk-sh-sm: 0 1px 2px rgba(45, 43, 43, .14);
  --sk-sh-md: 0 3px 10px rgba(45, 43, 43, .16);
  --sk-sh-lg: 0 12px 32px rgba(45, 43, 43, .22);
  --sk-r-scene: 26px;
  --sk-r-panel: 24px;
  --sk-r-drawer: 22px;
  --sk-r-card: 20px;
  --sk-r-block: 18px;
  --sk-r-tile: 13px;
  --sk-gap: clamp(16px, 2.4vw, 26px);

  display: flex;
  flex-direction: column;
  gap: var(--sk-gap);
  color: var(--sk-ink);
}

/* Der Grund der zwei Schirme ist wärmer als der der Reise — die Lieferung
   verlangt #f3f2f2, und die Karten darauf sind weiss. */
body.jr-page[data-jr-station="launch_station"] .jr-shell,
body.jr-page[data-jr-station="bestellungen_empfangen"] .jr-shell {
  background: var(--jr-card);
}

/* ── der Honigtopf, unsichtbar aber nicht `display:none` ─────────────────── */
.jr-sk .jr-hp,
.jr-be .jr-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  opacity: 0;
}
.jr-sk-forms { display: contents; }

/* ── Kopfzeile der Station ────────────────────────────────────────────────── */
.jr-sk-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding-block-end: 2px;
  border-block-end: 1px solid var(--sk-n200);
}
.jr-sk-head__where {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-inline-end: auto;
  min-width: 0;
}
.jr-sk-head__kicker {
  font-family: inherit;
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--sk-n600);
}
.jr-sk-head__name:not([hidden]) {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(19px, 2.3vw, 27px);
  letter-spacing: -.025em;
  line-height: 1.1;
}
.jr-sk-dot {
  inline-size: 9px;
  block-size: 9px;
  border-radius: 999px;
  background: var(--sk-acc);
  display: block;
  flex: none;
}
.jr-sk-ghost {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding-inline: 16px;
  border: 1px solid var(--sk-n300);
  border-radius: 999px;
  background: var(--sk-card);
  color: var(--sk-ink);
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.jr-sk-ghost:hover { background: var(--sk-n100); border-color: var(--sk-n400); }

/* ── die Bestelllink-Leiste ───────────────────────────────────────────────── */
.jr-sk-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  background: var(--sk-card);
  border: 1px solid var(--sk-n200);
  border-radius: var(--sk-r-block);
  padding: 12px 14px;
  box-shadow: var(--sk-sh-sm);
}
.jr-sk-strip__ico {
  inline-size: 34px;
  block-size: 34px;
  border-radius: 10px;
  background: var(--sk-acc100);
  color: var(--sk-acc);
  display: grid;
  place-items: center;
  flex: none;
}
.jr-sk-strip__ico svg { inline-size: 17px; block-size: 17px; }
.jr-sk-strip__body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 200px; }
.jr-sk-strip__url {
  font-family: inherit;
  font-weight: 500;
  font-size: 13.5px;
  color: var(--sk-ink);
  overflow-wrap: anywhere;
  text-decoration: none;
}
.jr-sk-strip__url:hover { text-decoration: underline; }
.jr-sk-strip__acts { display: flex; gap: 8px; flex: none; flex-wrap: wrap; }

.jr-over {
  font-family: inherit;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sk-n600);
}
.jr-over--accent { color: var(--sk-acc700); letter-spacing: .2em; font-weight: 700; }

/* ── die Einleitung ───────────────────────────────────────────────────────── */
.jr-sk-intro { display: flex; flex-direction: column; gap: clamp(10px, 1.4vw, 16px); }
.jr-sk-intro__t:not([hidden]) {
  margin: 0;
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(26px, 4.4vw, 46px);
  line-height: 1.1;
  letter-spacing: -.03em;
  max-width: 22ch;
  animation: sk-line .8s cubic-bezier(.2, .8, .25, 1) both;
}
.jr-sk-intro__s:not([hidden]) {
  margin: 0;
  font-family: inherit;
  font-weight: 400;
  font-size: clamp(15px, 1.7vw, 19px);
  line-height: 1.55;
  color: var(--sk-n700);
  max-width: 60ch;
  animation: sk-line .8s cubic-bezier(.2, .8, .25, 1) .12s both;
}

/* ── die Szene ────────────────────────────────────────────────────────────── */
.jr-sk-scene {
  container-type: inline-size;
  background: var(--sk-card);
  border-radius: var(--sk-r-scene);
  box-shadow: var(--sk-sh-md);
  padding: clamp(18px, 3vw, 36px);
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2.4vw, 26px);
  animation: sk-scene .55s cubic-bezier(.2, .8, .25, 1) both;
}
.jr-sk-scene__head { display: flex; flex-direction: column; gap: 8px; }
.jr-sk-kick {
  margin: 0;
  display: flex;
  align-items: center;
  gap: .4em;
  flex-wrap: wrap;
  font-family: inherit;
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--sk-acc700);
}
.jr-sk-h2:not([hidden]) {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(26px, 3.6vw, 40px);
  line-height: 1.1;
  letter-spacing: -.03em;
}
.jr-sk-sub:not([hidden]) {
  margin: 0;
  font-family: inherit;
  font-weight: 400;
  font-size: clamp(15px, 1.7vw, 19px);
  line-height: 1.5;
  color: var(--sk-n700);
  max-width: 56ch;
  animation: sk-rise .6s ease .2s both;
}

/* die Kachel eines Werkzeugs — Fläche und Tinte kommen als Marken vom Markup */
.jr-sk-tile {
  inline-size: clamp(38px, 4vw, 46px);
  block-size: clamp(38px, 4vw, 46px);
  border-radius: 14px;
  background: var(--sk-tint, var(--sk-n100));
  color: var(--sk-ink);
  display: grid;
  place-items: center;
  flex: none;
  animation: sk-pop .7s cubic-bezier(.2, .85, .3, 1) .1s both;
}
.jr-sk-tile svg { inline-size: 55%; block-size: 55%; color: var(--sk-ink); }
.jr-sk-tile > svg { stroke: currentColor; }
.jr-sk-tile__l {
  font-family: inherit;
  font-weight: 800;
  font-size: clamp(21px, 2.4vw, 26px);
  line-height: 1;
  color: var(--sk-ink);
}
.jr-sk-tile--sm { inline-size: 42px; block-size: 42px; border-radius: var(--sk-r-tile); }
.jr-sk-tile--sm .jr-sk-tile__l { font-size: 21px; }
.jr-sk-tile--lg { inline-size: 46px; block-size: 46px; border-radius: 14px; }
/* Die Tinte der Kachel ist eine Marke, damit die Farbe an EINER Stelle steht
   (journey_startklar_tools()) und nicht sechsmal im Stylesheet. */
.jr-sk-tile { color: var(--sk-ink); }

/* ── zweispaltig, aber als Container-Frage ────────────────────────────────── */
.jr-sk-two {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(16px, 2.2vw, 24px);
  align-items: start;
}
@container (min-width: 620px) {
  .jr-sk-two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.jr-sk-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

/* ── Werkzeug 1 · QR ──────────────────────────────────────────────────────── */
.jr-sk-qr { display: flex; flex-direction: column; gap: clamp(14px, 2vw, 20px); }
.jr-sk-qr__code {
  align-self: flex-start;
  inline-size: clamp(104px, 12vw, 132px);
  block-size: clamp(104px, 12vw, 132px);
  background: var(--sk-card);
  border-radius: 16px;
  box-shadow: var(--sk-sh-md);
  padding: 8px;
  display: grid;
  place-items: center;
  animation: sk-pop .7s cubic-bezier(.2, .85, .3, 1) .1s both;
}
.jr-sk-qr__code img { inline-size: 100%; block-size: auto; display: block; }
.jr-sk-vids {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(14px, 2vw, 20px);
}
@container (min-width: 560px) {
  .jr-sk-vids { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.jr-sk-vid { margin: 0; display: flex; flex-direction: column; gap: 12px; }
.jr-sk-vid__box {
  position: relative;
  display: block;
  inline-size: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--sk-r-block);
  overflow: hidden;
  background: var(--sk-card);
  border: 1px solid var(--sk-n200);
}
.jr-sk-vid__box video {
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  display: block;
}
.jr-sk-vid__ai {
  position: absolute;
  inset-inline-start: 10px;
  inset-block-end: 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, .92);
  border-radius: 999px;
  padding: 5px 10px;
  font-family: inherit;
  font-weight: 600;
  font-size: 10.5px;
  line-height: 1.2;
  letter-spacing: .04em;
  color: var(--sk-n700);
}
.jr-sk-vid__ai::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  flex: none;
  background: var(--sk-acc);
  clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
}
.jr-sk-vid__say { display: flex; flex-direction: column; gap: 5px; }
.jr-sk-vid__t:not([hidden]) {
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(16px, 1.9vw, 19px);
  line-height: 1.25;
  letter-spacing: -.015em;
}
.jr-sk-vid__s {
  font-family: inherit;
  font-weight: 400;
  font-size: 14px;
  line-height: 1.6;
  color: var(--sk-n700);
}
.jr-sk-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  border-block-start: 1px solid var(--sk-n200);
  padding-block-start: clamp(14px, 2vw, 20px);
}
.jr-sk-foot__t:not([hidden]) {
  flex: 1 1 240px;
  font-family: inherit;
  font-weight: 600;
  font-size: clamp(15px, 1.8vw, 18px);
  line-height: 1.35;
  letter-spacing: -.01em;
}

/* ── Knöpfe ───────────────────────────────────────────────────────────────── */
.jr-sk-acts { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; }
.jr-sk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding-inline: 18px;
  border: 1px solid var(--sk-n300);
  border-radius: 999px;
  background: var(--sk-card);
  color: var(--sk-ink);
  font-family: inherit;
  font-weight: 600;
  font-size: 14.5px;
  line-height: 1.25;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.jr-sk-btn:hover { background: var(--sk-n100); border-color: var(--sk-n400); }
.jr-sk-btn--primary {
  border: 0;
  padding-inline: 20px;
  background: var(--sk-acc);
  color: #ffffff;
  box-shadow: var(--sk-sh-sm);
}
.jr-sk-btn--primary:hover { background: var(--sk-acc600); }
.jr-sk-btn--primary:active { background: var(--sk-acc700); }
.jr-sk-btn__ico { display: inline-flex; flex: none; }
.jr-sk-btn__ico svg { inline-size: 16px; block-size: 16px; }
.jr-sk-btn__ico--end { order: 2; }
/* ⛔ EIN GEDREHTER PFEIL, KEIN GEDREHTES MARKUP — n12-Gate D7. */
[dir="rtl"] .jr-sk-btn__ico--end svg { transform: scaleX(-1); }

/* ⭐⭐ DER KOPIER-KNOPF IST OHNE SKRIPT NICHT DA. Er kann ohne Skript nichts
   tun, und der Text daneben ist markierbar — ein Knopf, der nichts tut, ist
   schlechter als kein Knopf. jr-startklar.js meldet sich am Abschnitt an. */
.jr-sk-copy { display: none; }
[data-jr-sk-js] .jr-sk-copy { display: inline-flex; }

/* ── Vorschauen (Facebook, Instagram, TikTok, Google, WhatsApp) ───────────── */
.jr-sk-prev {
  border: 1px solid var(--sk-n200);
  border-radius: var(--sk-r-block);
  background: var(--sk-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  animation: sk-pop .6s cubic-bezier(.2, .85, .3, 1) .15s both;
  min-width: 0;
}
.jr-sk-prev--tall { align-items: center; background: transparent; border: 0; padding: 0; }
.jr-sk-prev__head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.jr-sk-prev__who { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.jr-sk-prev__n {
  font-family: inherit;
  font-weight: 700;
  font-size: 14px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.jr-sk-prev__m { font-family: inherit; font-size: 11.5px; line-height: 1.35; color: var(--sk-n600); }
.jr-sk-prev__m--ok { color: var(--sk-ok-ink); font-weight: 600; display: inline-flex; align-items: center; gap: 6px; }
.jr-sk-prev__m--ok::before {
  content: "";
  inline-size: 6px;
  block-size: 6px;
  border-radius: 999px;
  background: var(--sk-ok);
  flex: none;
}
.jr-sk-prev__link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 12px;
  background: var(--sk-n100);
  border-radius: 12px;
  min-width: 0;
}
.jr-sk-prev__host {
  font-family: inherit;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--sk-n600);
  overflow-wrap: anywhere;
}
.jr-sk-prev__cta { font-family: inherit; font-weight: 600; font-size: 13px; margin-inline-start: auto; }

.jr-sk-ava {
  inline-size: 36px;
  block-size: 36px;
  border-radius: 999px;
  background: var(--sk-acc);
  color: #ffffff;
  display: grid;
  place-items: center;
  flex: none;
  font-family: inherit;
  font-weight: 700;
  font-size: 13px;
  line-height: 1;
}
.jr-sk-ava--lg { inline-size: 52px; block-size: 52px; font-size: 17px; }
.jr-sk-ava--xs { inline-size: 24px; block-size: 24px; font-size: 10.5px; border-radius: 8px; }
.jr-sk-ava--ping { position: relative; }
/* Derselbe Griff wie beim Finale-Haken: der Ring bleibt im Kasten und wächst
   nur per `transform` heraus — ein negativer `inset` macht das Element für jede
   Messung breiter, als es ist. */
.jr-sk-ava--ping::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 999px;
  border: 2px solid #e1306c;
  animation: sk-ping 2.6s cubic-bezier(.25, 0, .35, 1) 1.2s infinite;
}

/* die Zeile, die einrastet */
.jr-sk-snap {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1.5px solid var(--sk-acc);
  background: var(--sk-acc100);
  border-radius: 14px;
  padding: 11px 12px;
  animation: sk-snap .8s cubic-bezier(.25, .9, .3, 1) .7s both;
  min-width: 0;
}
.jr-sk-snap--edge { border: 1px solid var(--sk-n200); border-inline-start: 3px solid var(--sk-acc); border-radius: 12px; }
.jr-sk-snap__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.jr-sk-snap__k {
  font-family: inherit;
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--sk-acc700);
}
.jr-sk-snap__v { font-family: inherit; font-weight: 600; font-size: 12.5px; overflow-wrap: anywhere; }
.jr-sk-snap > .jr-sk-snap__k,
.jr-sk-snap > .jr-sk-snap__v { display: block; }
.jr-sk-snap:not(.jr-sk-snap--ok):not(.jr-sk-snap--edge) { flex-direction: column; align-items: stretch; gap: 2px; }
.jr-sk-snap__ok {
  inline-size: 24px;
  block-size: 24px;
  border-radius: 999px;
  background: var(--sk-ok);
  display: grid;
  place-items: center;
  flex: none;
  animation: sk-badge .5s cubic-bezier(.2, .9, .3, 1) 1.5s both;
}
.jr-sk-snap__ok svg { inline-size: 13px; block-size: 13px; }

/* Instagram: das Drei-Raster */
.jr-sk-grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.jr-sk-grid3__c { border-radius: 8px; overflow: hidden; display: block; }
.jr-sk-grid3__e { aspect-ratio: 1 / 1; border-radius: 8px; background: var(--sk-n200); display: block; }
.jr-sk-grid3__e:last-child { background: var(--sk-n100); }

/* TikTok: hochkant */
.jr-sk-tall {
  position: relative;
  display: block;
  inline-size: min(240px, 78%);
  min-inline-size: 190px;
  border-radius: var(--sk-r-card);
  overflow: hidden;
  box-shadow: var(--sk-sh-md);
  background: var(--sk-ink);
}
.jr-sk-tall__sheen {
  position: absolute;
  inset-block: 0;
  inline-size: 44px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .42), rgba(255, 255, 255, 0));
  animation: sk-sheen 4.4s cubic-bezier(.4, 0, .3, 1) 1.2s infinite;
  pointer-events: none;
}
.jr-sk-tall__foot {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px;
  background: linear-gradient(180deg, rgba(32, 30, 29, 0), rgba(32, 30, 29, .86));
}
.jr-sk-tall__h { font-family: inherit; font-weight: 600; font-size: 11.5px; color: #ffffff; }
.jr-sk-tall__pill {
  margin-inline-start: auto;
  background: #ffffff;
  border-radius: 999px;
  padding: 5px 10px;
  font-family: inherit;
  font-weight: 700;
  font-size: 10.5px;
  color: var(--sk-ink);
  white-space: nowrap;
}

/* Google: das Unternehmensprofil */
.jr-sk-search {
  display: flex;
  align-items: center;
  gap: 9px;
  border: 1px solid var(--sk-n200);
  border-radius: 999px;
  padding: 9px 13px;
  min-width: 0;
}
.jr-sk-search__i { display: inline-flex; color: var(--sk-n500); flex: none; }
.jr-sk-search__i svg { inline-size: 15px; block-size: 15px; }
.jr-sk-search__t { font-family: inherit; font-size: 13px; color: var(--sk-n700); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr-sk-gname:not([hidden]) { font-family: inherit; font-weight: 700; font-size: 17px; line-height: 1.25; letter-spacing: -.015em; }
.jr-sk-gkind { font-family: inherit; font-size: 12.5px; color: var(--sk-n700); }
.jr-sk-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.jr-sk-chip {
  border: 1px solid var(--sk-n300);
  border-radius: 999px;
  padding: 6px 12px;
  font-family: inherit;
  font-weight: 600;
  font-size: 12px;
  line-height: 1.2;
  color: var(--sk-n800);
}

/* WhatsApp: Profilfelder und Verlauf */
.jr-sk-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border: 1px solid var(--sk-n200);
  border-radius: 14px;
  padding: 10px 12px;
}
.jr-sk-fields__h {
  font-family: inherit;
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sk-n600);
}
.jr-sk-fields__r { font-family: inherit; font-size: 12.5px; line-height: 1.5; color: var(--sk-n700); }
.jr-sk-chat {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: #e5ded7;
  border-radius: 14px;
  padding: 12px;
}
.jr-sk-chat__me,
.jr-sk-chat__you {
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.5;
  padding: 9px 11px;
  max-width: 88%;
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.jr-sk-chat__me {
  align-self: flex-end;
  background: #dcf8c6;
  border-radius: 12px 12px 4px 12px;
  max-width: 82%;
}
.jr-sk-chat__you {
  align-self: flex-start;
  background: #ffffff;
  border-radius: 12px 12px 12px 4px;
  box-shadow: var(--sk-sh-sm);
}
[dir="rtl"] .jr-sk-chat__me { border-radius: 12px 12px 12px 4px; }
[dir="rtl"] .jr-sk-chat__you { border-radius: 12px 12px 4px 12px; }
.jr-sk-chat__pill {
  align-self: center;
  background: #ffffff;
  border-radius: 999px;
  padding: 5px 10px;
  font-family: inherit;
  font-weight: 600;
  font-size: 10.5px;
  color: var(--sk-ok-ink);
}

/* ── Schritte, Textkästen, Hinweise ──────────────────────────────────────── */
.jr-sk-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.jr-sk-step { display: flex; align-items: center; gap: 10px; }
.jr-sk-step__n {
  inline-size: 24px;
  block-size: 24px;
  border-radius: 999px;
  background: var(--sk-acc100);
  color: var(--sk-acc700);
  display: grid;
  place-items: center;
  flex: none;
  font-family: inherit;
  font-weight: 700;
  font-size: 12px;
  line-height: 1;
}
.jr-sk-step:first-child .jr-sk-step__n { background: var(--sk-acc); color: #ffffff; }
.jr-sk-step__t { font-family: inherit; font-size: 14px; line-height: 1.45; }
.jr-sk-box2 {
  border: 1px solid var(--sk-n200);
  border-radius: 16px;
  padding: 14px;
  background: var(--sk-n100);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.jr-sk-tpl {
  margin: 0;
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.6;
  white-space: pre-line;
  color: var(--sk-n900);
  overflow-wrap: anywhere;
}
.jr-sk-hint { margin: 0; font-family: inherit; font-size: 13px; line-height: 1.55; color: var(--sk-n600); }
.jr-sk-expl { margin: 0; font-family: inherit; font-size: 14px; line-height: 1.6; color: var(--sk-n800); }
.jr-sk-note { margin: 0; font-family: inherit; font-size: 12px; line-height: 1.5; color: var(--sk-n600); }
.jr-sk-ul { margin: 0; padding-inline-start: 18px; display: flex; flex-direction: column; gap: 7px; }
.jr-sk-ul li { font-family: inherit; font-size: 14px; line-height: 1.5; color: var(--sk-n800); }

/* ── das Promo-Bild ──────────────────────────────────────────────────────────
   ⭐⭐ DIE DREI ZAHLEN KOMMEN AUS DEM MARKUP (`--sk-cx/--sk-cy/--sk-box`), und
   dort aus journey_startklar_promo_geometry() — derselben Funktion, mit der
   api/journey/promo_image.php die Datei zeichnet. Zwei Zeichenwege, eine
   Quelle: ein zweiter Satz Zahlen wäre der Tag, an dem Vorschau und Download
   auseinanderlaufen.
   ⚠️ Der Teller ist NICHT bildmittig — mit 50/50 sitzt das Logo sichtbar
   falsch. Aus den Bildpunkten gemessen, nicht geschätzt. */
.jr-sk-promo {
  container-type: inline-size;
  position: relative;
  display: block;
  inline-size: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: #141312;
  border-radius: 12px;
  animation: sk-pop .6s cubic-bezier(.2, .85, .3, 1) .3s both;
}
.jr-sk-promo__photo {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  display: block;
}
.jr-sk-promo__logo,
.jr-sk-promo__slot,
.jr-sk-promo__ring {
  position: absolute;
  inset-inline-start: var(--sk-cx, 51.32%);
  inset-block-start: var(--sk-cy, 48.25%);
  transform: translate(-50%, -50%);
  inline-size: var(--sk-box, 41%);
  aspect-ratio: 1 / 1;
  border-radius: 999px;
  display: grid;
  place-items: center;
}
[dir="rtl"] .jr-sk-promo__logo,
[dir="rtl"] .jr-sk-promo__slot,
[dir="rtl"] .jr-sk-promo__ring {
  /* ⛔ DAS BILD SPIEGELT NICHT MIT. Es ist ein Foto mit einer gemessenen
     Stelle; `inset-inline-start` würde unter RTL von rechts messen und das
     Logo neben den Teller setzen. Hier zählt links, in jeder Sprache. */
  inset-inline-start: auto;
  left: var(--sk-cx, 51.32%);
}
.jr-sk-promo__slot {
  border: 1.5px dashed rgba(255, 255, 255, .5);
  animation: pi-slot 5.6s cubic-bezier(.3, .7, .3, 1) both infinite;
}
.jr-sk-promo__ring {
  inline-size: calc(var(--sk-box, 41%) + 3%);
  border: 2px solid rgba(255, 255, 255, .85);
  animation: pi-ring 5.6s cubic-bezier(.25, .6, .3, 1) both infinite;
}
.jr-sk-promo__logo {
  background: #ffffff;
  box-shadow: 0 2cqw 6cqw rgba(0, 0, 0, .45);
  overflow: hidden;
  animation: pi-logo 5.6s cubic-bezier(.2, .85, .3, 1) both infinite;
}
.jr-sk-promo__logo img { inline-size: 72%; block-size: 72%; object-fit: contain; display: block; }
.jr-sk-promo__name {
  font-family: inherit;
  font-weight: 700;
  font-size: 5cqw;
  line-height: 1.15;
  text-align: center;
  color: var(--sk-ink);
  padding: 8%;
  overflow-wrap: anywhere;
}
.jr-sk-promo__cta {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: 5cqw 5cqw 4cqw;
  background: linear-gradient(180deg, rgba(20, 19, 18, 0), rgba(20, 19, 18, .88));
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 4cqw;
  animation: pi-cta 5.6s cubic-bezier(.2, .8, .25, 1) both infinite;
}
.jr-sk-promo__head:not([hidden]) {
  font-family: inherit;
  font-weight: 700;
  font-size: 5.6cqw;
  line-height: 1.1;
  letter-spacing: -.03em;
  color: #ffffff;
  min-width: 0;
}
.jr-sk-promo__url {
  display: block;
  font-family: inherit;
  font-size: 2.9cqw;
  line-height: 1.3;
  color: rgba(255, 255, 255, .82);
  overflow-wrap: anywhere;
  margin-block-start: 1.4cqw;
}
.jr-sk-promo__qr {
  inline-size: 12cqw;
  block-size: 12cqw;
  flex: none;
  background: #ffffff;
  border-radius: 1.6cqw;
  padding: 1.2cqw;
  display: grid;
  place-items: center;
}
.jr-sk-promo__qr img { inline-size: 100%; block-size: 100%; display: block; }
.jr-sk-promo__mark {
  position: absolute;
  inset-inline-end: 3cqw;
  inset-block-start: 3cqw;
  display: inline-flex;
  align-items: center;
  gap: 1.4cqw;
  background: rgba(20, 19, 18, .62);
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 999px;
  padding: 1.4cqw 2.4cqw;
  font-family: inherit;
  font-weight: 600;
  font-size: 2.3cqw;
  line-height: 1.2;
  letter-spacing: .06em;
  color: rgba(255, 255, 255, .92);
  animation: pi-mark 5.6s linear both infinite;
}

/* ── das Finale ───────────────────────────────────────────────────────────── */
.jr-sk-fin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(14px, 2vw, 26px);
  background: var(--sk-card);
  border-radius: var(--sk-r-panel);
  padding: clamp(18px, 2.6vw, 28px);
  box-shadow: var(--sk-sh-sm);
  animation: sk-scene .6s cubic-bezier(.2, .8, .25, 1) both;
}
/* 🔴 DER RING GEHÖRT IN DEN KASTEN, NICHT DARÜBER HINAUS. Erste Fassung: ein
   46-px-Kreis mit `::after { inset: -3px }` — der Ring ragte drei Pixel nach
   aussen und die Sonde meldete `52 > 46`, also einen Kasten, der seinen Inhalt
   abschneidet. Auf diesem Schirm war es harmlos (nichts clippt dort), aber die
   Messung kann das nicht wissen, und ein Kasten, der 6 px mehr misst als er
   zugibt, ist genau die Sorte Angabe, die beim nächsten Umbau in einem
   `overflow: clip` landet.
   ⇒ Die Kachel ist jetzt 52 px gross und TRANSPARENT; der grüne Kreis ist ihr
   `::before` (46 px, mittig), der Ring ihr `::after` bei `inset: 0`. Alles
   liegt drin, das Bild ist unverändert. */
.jr-sk-fin__mark {
  position: relative;
  inline-size: 52px;
  block-size: 52px;
  flex: none;
  display: grid;
  place-items: center;
  animation: sk-pop .7s cubic-bezier(.2, .9, .3, 1) both;
}
.jr-sk-fin__mark::before {
  content: "";
  grid-area: 1 / 1;
  inline-size: 46px;
  block-size: 46px;
  border-radius: 999px;
  background: var(--sk-ok);
}
.jr-sk-fin__mark svg { grid-area: 1 / 1; inline-size: 24px; block-size: 24px; place-self: center; }
.jr-sk-fin__mark::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 999px;
  border: 2px solid var(--sk-ok);
  animation: sk-ping 3s cubic-bezier(.25, 0, .35, 1) .6s infinite;
}
.jr-sk-fin__say { display: flex; flex-direction: column; gap: 6px; flex: 1 1 260px; min-width: 0; }
.jr-sk-fin__t:not([hidden]) {
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(22px, 2.8vw, 32px);
  line-height: 1.15;
  letter-spacing: -.025em;
}
.jr-sk-fin__s { font-family: inherit; font-size: clamp(14px, 1.5vw, 16px); line-height: 1.55; color: var(--sk-n700); max-width: 62ch; }

/* ── der Werkzeugkasten ───────────────────────────────────────────────────── */
.jr-sk-box { display: flex; flex-direction: column; gap: clamp(12px, 1.6vw, 16px); scroll-margin-block-start: 90px; }
.jr-sk-box__head { margin: 0; display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.jr-sk-box__count { display: inline-flex; gap: .35em; font-family: inherit; font-size: 12.5px; color: var(--sk-n600); }
.jr-sk-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(252px, 1fr));
  gap: clamp(12px, 1.6vw, 16px);
}
.jr-sk-card {
  position: relative;
  background: var(--sk-card);
  border: 1px solid var(--sk-n200);
  border-radius: var(--sk-r-card);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  animation: sk-land .6s cubic-bezier(.2, .85, .3, 1) both;
  transition: box-shadow .18s ease, transform .18s ease;
}
.jr-sk-card:hover { box-shadow: var(--sk-sh-md); transform: translateY(-2px); }
.jr-sk-card--link { background: var(--sk-n100); border-style: dashed; border-color: var(--sk-n300); }
.jr-sk-card--link:hover { transform: none; box-shadow: none; }
.jr-sk-card__top { display: flex; align-items: flex-start; gap: 11px; }
.jr-sk-card__say { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.jr-sk-card__link,
.jr-sk-card__t {
  font-family: inherit;
  font-weight: 700;
  font-size: 15.5px;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--sk-ink);
  text-decoration: none;
}
/* ⭐ DER GEDEHNTE LINK: die ganze Karte ist anklickbar, ohne dass ein Knopf in
   einem Link steckt (ungültiges HTML, das je nach Browser eine der beiden
   Aktionen verschluckt). Die Schnellaktion liegt mit `z-index` darüber. */
.jr-sk-card__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.jr-sk-card__link:focus-visible { outline: none; }
.jr-sk-card__link:focus-visible::after { outline: 2px solid var(--sk-acc); outline-offset: 2px; }
.jr-sk-card__p { font-family: inherit; font-size: 12.5px; line-height: 1.4; color: var(--sk-n700); overflow-wrap: anywhere; }
.jr-sk-card__chev { color: var(--sk-n500); flex: none; margin-block-start: 3px; }
.jr-sk-card__chev svg { inline-size: 18px; block-size: 18px; }
.jr-sk-card__foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.jr-sk-card__foot--acts { gap: 8px; }
.jr-sk-card__act { margin-inline-start: auto; position: relative; z-index: 1; }
.jr-sk-card__foot--acts > * { position: relative; z-index: 1; }
.jr-sk-card .jr-sk-btn { min-height: 44px; padding-inline: 15px; font-size: 13px; }

.jr-sk-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--sk-ok-soft);
  color: var(--sk-ok-ink);
  border-radius: 999px;
  padding: 5px 10px;
  font-family: inherit;
  font-weight: 600;
  font-size: 12px;
  line-height: 1.2;
  white-space: nowrap;
}
/* ⛔ ZUSTAND NIE NUR ÜBER FARBE — die Plakette trägt immer ihren Haken. */
.jr-sk-pill::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  flex: none;
  background: currentColor;
  clip-path: polygon(14% 48%, 5% 60%, 38% 92%, 96% 22%, 86% 12%, 37% 71%);
}

/* ── die Schubladen (`:target`) ───────────────────────────────────────────── */
.jr-sk-drawer { display: none; }
.jr-sk-drawer:target {
  display: flex;
  flex-direction: column;
  gap: 16px;
  background: var(--sk-card);
  border: 1.5px solid var(--sk-acc);
  border-radius: var(--sk-r-drawer);
  padding: clamp(16px, 2.4vw, 24px);
  animation: sk-drawer .34s cubic-bezier(.2, .8, .25, 1) both;
  scroll-margin-block-start: 90px;
}
.jr-sk-drawer__head { display: flex; align-items: flex-start; gap: 12px; }
.jr-sk-drawer__say { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.jr-sk-drawer__t:not([hidden]) {
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(18px, 2.2vw, 22px);
  line-height: 1.25;
  letter-spacing: -.02em;
}
.jr-sk-x {
  inline-size: 34px;
  block-size: 34px;
  border: 1px solid var(--sk-n300);
  border-radius: 999px;
  background: var(--sk-card);
  color: var(--sk-ink);
  display: grid;
  place-items: center;
  flex: none;
  text-decoration: none;
  font-size: 18px;
  line-height: 1;
}
.jr-sk-x:hover { background: var(--sk-n100); }
.jr-sk-drawer__body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  align-items: start;
}
.jr-sk-drawer__side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.jr-sk-drawer__pic { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.jr-sk-drawer__qr {
  inline-size: min(190px, 100%);
  aspect-ratio: 1 / 1;
  background: var(--sk-card);
  border-radius: 16px;
  box-shadow: var(--sk-sh-md);
  padding: 10px;
  display: grid;
  place-items: center;
}
.jr-sk-drawer__qr img { inline-size: 100%; block-size: auto; display: block; }

/* ── die Leiste mit dem einen Knopf ───────────────────────────────────────── */
.jr-sk-bar {
  position: sticky;
  inset-block-end: 0;
  z-index: 5;
  margin-inline: calc(var(--jr-gutter, 20px) * -1);
  padding: clamp(14px, 2vw, 20px) var(--jr-gutter, 20px) clamp(16px, 2.4vw, 24px);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .96) 34%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
/* ⛔ ÜBER DEM COOKIE-BANNER, wie `.jr-foot` seit dem 24.08.2026 — er liegt
   `position: fixed` am unteren Rand und würde diesen Knopf auf dem Telefon
   sonst verdecken. Dieselbe Marke, derselbe Grund. */
body.cookie-banner-visible .jr-sk-bar { inset-block-end: var(--ui-cookie-banner-height, 0px); }
.jr-sk-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 54px;
  padding-inline: 28px;
  border: 0;
  border-radius: 999px;
  background: var(--sk-acc);
  color: #ffffff;
  font-family: inherit;
  font-weight: 600;
  font-size: 15.5px;
  line-height: 1.25;
  cursor: pointer;
  box-shadow: var(--sk-sh-md);
  white-space: normal;
  text-align: center;
}
.jr-sk-go:hover { background: var(--sk-acc600); }
.jr-sk-go:active { background: var(--sk-acc700); }
.jr-sk-go::after {
  content: "";
  inline-size: 17px;
  block-size: 17px;
  flex: none;
  background: currentColor;
  clip-path: polygon(0 44%, 62% 44%, 44% 16%, 56% 6%, 100% 50%, 56% 94%, 44% 84%, 62% 56%, 0 56%);
}
[dir="rtl"] .jr-sk-go::after { transform: scaleX(-1); }
.jr-sk-prog { margin: 0; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: center; }
.jr-sk-dots { display: inline-flex; gap: 6px; }
.jr-sk-dots__d {
  inline-size: 7px;
  block-size: 7px;
  border-radius: 999px;
  /* ⚠️ #d7d3d3, NICHT rgba(255,255,255,.28) wie im Prototyp: auf dem hellen
     Verlauf dieser Leiste wäre Weiss bei 28 % unsichtbar. Der Text der
     Lieferung nennt selbst #d7d3d3; der Prototyp widerspricht sich hier. */
  background: var(--sk-n300);
  display: block;
}
.jr-sk-dots__d.is-on { background: var(--sk-acc); }
.jr-sk-prog__t {
  display: inline-flex;
  gap: .35em;
  font-family: inherit;
  font-weight: 600;
  font-size: 12.5px;
  color: var(--sk-n600);
  white-space: nowrap;
}

/* ══════════════════════════════════════════════════════════════════════════
   Station 16 · «Bestellungen empfangen»
   ══════════════════════════════════════════════════════════════════════════ */

.jr-be-hero {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(18px, 3vw, 40px);
  align-items: center;
}
@media (min-width: 834px) {
  .jr-be-hero { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); }
}
.jr-be-hero__say { display: flex; flex-direction: column; gap: clamp(12px, 1.6vw, 18px); min-width: 0; }
.jr-be-h1:not([hidden]) {
  margin: 0;
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(27px, 4.2vw, 44px);
  line-height: 1.12;
  letter-spacing: -.03em;
  max-width: 20ch;
  animation: be-line .8s cubic-bezier(.2, .8, .25, 1) both;
}
.jr-be-lede:not([hidden]) {
  margin: 0;
  font-family: inherit;
  font-weight: 400;
  font-size: clamp(15px, 1.7vw, 18px);
  line-height: 1.55;
  color: var(--sk-n700);
  max-width: 52ch;
  animation: be-rise .7s ease .2s both;
}
.jr-be-feats { margin: 0; display: flex; flex-wrap: wrap; gap: 18px; animation: be-rise .7s ease .35s both; }
.jr-be-feat { display: inline-flex; align-items: center; gap: 9px; font-family: inherit; font-size: 13.5px; line-height: 1.4; color: var(--sk-n800); }
.jr-be-feat__i { display: inline-flex; color: var(--sk-acc); flex: none; }
.jr-be-feat__i svg { inline-size: 17px; block-size: 17px; }

/* das Telefon */
.jr-be-phone {
  position: relative;
  justify-self: center;
  inline-size: min(258px, 78%);
  min-inline-size: 214px;
  aspect-ratio: 9 / 17.6;
  border: 9px solid var(--sk-ink);
  border-radius: 34px;
  background: var(--sk-card);
  box-shadow: var(--sk-sh-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  animation: be-pop .8s cubic-bezier(.2, .85, .3, 1) .15s both;
}
.jr-be-phone__notch {
  position: absolute;
  inset-block-start: 7px;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  inline-size: 56px;
  block-size: 5px;
  border-radius: 999px;
  background: var(--sk-ink);
  z-index: 3;
}
.jr-be-phone__head {
  padding: 22px 13px 11px;
  display: flex;
  align-items: center;
  gap: 9px;
  border-block-end: 1px solid var(--sk-n200);
}
.jr-be-phone__t {
  font-family: inherit;
  font-weight: 700;
  font-size: 12.5px;
  line-height: 1.2;
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 🔬 24, NICHT 22 — GEMESSEN. Der Ring (`__ping`) liegt bei `inset: 0` und
   trägt 2 px Rahmen; bei 22 px meldete die Sonde `24 > 22`, also einen
   Kasten, der seinen eigenen Inhalt abschneidet. Zwei Pixel, die niemand
   sieht und die jede Messung sauber machen. */
.jr-be-phone__badge { position: relative; inline-size: 24px; block-size: 24px; flex: none; display: grid; place-items: center; }
.jr-be-phone__ping {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  border: 2px solid var(--sk-acc);
  animation: be-ping 7s cubic-bezier(.25, 0, .35, 1) .5s infinite;
}
.jr-be-phone__n {
  inline-size: 20px;
  block-size: 20px;
  border-radius: 999px;
  background: var(--sk-acc);
  color: #ffffff;
  display: grid;
  place-items: center;
  font-family: inherit;
  font-weight: 700;
  font-size: 10.5px;
  line-height: 1;
  animation: be-badge 7s ease .5s infinite;
}
.jr-be-phone__feed { position: relative; flex: 1; padding: 10px; display: flex; flex-direction: column; gap: 8px; background: var(--sk-n100); }
.jr-be-order {
  background: var(--sk-card);
  border-radius: 12px;
  padding: 10px;
  box-shadow: var(--sk-sh-md);
  display: flex;
  flex-direction: column;
  gap: 6px;
  animation: be-order 7s cubic-bezier(.2, .85, .3, 1) .5s infinite;
}
.jr-be-order__k {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-weight: 700;
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sk-acc700);
}
.jr-be-order__k::before { content: ""; inline-size: 6px; block-size: 6px; border-radius: 999px; background: var(--sk-acc); flex: none; }
.jr-be-order__i { font-family: inherit; font-weight: 700; font-size: 12.5px; line-height: 1.3; letter-spacing: -.01em; }
.jr-be-order__m { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-family: inherit; font-size: 11px; color: var(--sk-n600); }
.jr-be-order__m span:last-child { font-weight: 700; font-size: 12px; color: var(--sk-ink); }
.jr-be-list { display: flex; flex-direction: column; gap: 8px; animation: be-shift 7s cubic-bezier(.2, .85, .3, 1) .5s infinite; }
.jr-be-row { background: var(--sk-card); border-radius: 12px; padding: 10px; display: flex; flex-direction: column; gap: 5px; }
.jr-be-row--old { opacity: .72; }
.jr-be-row__i { font-family: inherit; font-weight: 600; font-size: 12px; line-height: 1.3; }

/* die drei Karten-Abschnitte */
.jr-be-card {
  background: var(--sk-card);
  border-radius: var(--sk-r-panel);
  box-shadow: var(--sk-sh-md);
  padding: clamp(18px, 2.6vw, 30px);
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2vw, 20px);
  animation: be-rise .7s ease .3s both;
  scroll-margin-block-start: 90px;
}
.jr-be-card__head { display: flex; flex-direction: column; gap: 5px; }
.jr-be-h2:not([hidden]) {
  margin: 0;
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(20px, 2.4vw, 26px);
  line-height: 1.2;
  letter-spacing: -.025em;
}
.jr-be-sub { margin: 0; font-family: inherit; font-size: 14px; line-height: 1.55; color: var(--sk-n700); max-width: 58ch; }

.jr-be-stores { display: grid; grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); gap: clamp(12px, 1.8vw, 16px); }
.jr-be-store { border: 1px solid var(--sk-n200); border-radius: var(--sk-r-block); padding: 16px; display: flex; flex-direction: column; gap: 14px; }
.jr-be-store__head { display: flex; align-items: center; gap: 11px; min-width: 0; }
.jr-be-store__say { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.jr-be-store__t:not([hidden]) { font-family: inherit; font-weight: 700; font-size: 15.5px; line-height: 1.3; letter-spacing: -.01em; }
.jr-be-store__s { font-family: inherit; font-size: 12.5px; line-height: 1.4; color: var(--sk-n700); }
.jr-be-store__go { display: flex; align-items: center; gap: 14px; }
.jr-be-store__qr {
  inline-size: 88px;
  block-size: 88px;
  flex: none;
  background: var(--sk-card);
  border: 1px solid var(--sk-n200);
  border-radius: 12px;
  padding: 6px;
  display: grid;
  place-items: center;
}
.jr-be-store__qr img { inline-size: 100%; block-size: auto; display: block; }
.jr-be-dark {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding-inline: 16px;
  border: 0;
  border-radius: 999px;
  background: var(--sk-ink);
  color: #ffffff;
  font-family: inherit;
  font-weight: 600;
  font-size: 14px;
  line-height: 1.25;
  text-decoration: none;
  text-align: center;
}
.jr-be-dark:hover { background: #3a3735; color: #ffffff; }

.jr-be-row2 {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--sk-n200);
  border-radius: var(--sk-r-block);
  padding: 14px 16px;
}
.jr-be-row2--white { background: var(--sk-card); border: 0; border-radius: 16px; }
.jr-be-row2__say { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 190px; }
.jr-be-row2__v { font-family: inherit; font-weight: 600; font-size: 15px; line-height: 1.4; overflow-wrap: anywhere; color: var(--sk-ink); }
.jr-be-row2__v--soft { font-weight: 400; font-size: 13.5px; color: var(--sk-n600); }
.jr-be-row2__v--link { text-decoration: none; }
.jr-be-row2__v--link:hover { text-decoration: underline; }
.jr-be-row2__act { display: flex; flex-wrap: wrap; gap: 9px; flex: none; }

.jr-be-access { border: 1px solid var(--sk-n200); border-radius: var(--sk-r-block); padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; }
.jr-be-access__head { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.jr-be-to { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; background: var(--sk-n100); border-radius: 14px; padding: 11px 13px; }
.jr-be-to__k { font-family: inherit; font-size: 13px; color: var(--sk-n700); }
.jr-be-to__v { font-family: inherit; font-weight: 700; font-size: 14.5px; overflow-wrap: anywhere; }
.jr-be-ok { display: flex; align-items: flex-start; gap: 11px; cursor: pointer; font-family: inherit; font-size: 13.5px; line-height: 1.5; color: var(--sk-n800); }
.jr-be-ok input { inline-size: 22px; block-size: 22px; flex: none; margin: 1px 0 0; accent-color: var(--sk-acc); cursor: pointer; }
.jr-be-send { min-height: 52px; font-size: 15px; }
.jr-be-send.is-waiting { background: var(--sk-n200); color: var(--sk-n600); box-shadow: none; }

.jr-be-banner {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  border-radius: 14px;
  padding: 11px 13px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.45;
}
.jr-be-banner--ok { background: var(--sk-ok-soft); color: var(--sk-ok-deep); }
.jr-be-banner--bad { background: var(--jr-amber-soft); color: var(--jr-amber-ink); }
.jr-be-banner__i { inline-size: 24px; block-size: 24px; border-radius: 999px; display: grid; place-items: center; flex: none; background: currentColor; }
.jr-be-banner__i svg { inline-size: 13px; block-size: 13px; stroke: #ffffff; }
.jr-be-banner__wait {
  margin-inline-start: auto;
  font-family: inherit;
  font-weight: 700;
  font-size: 12.5px;
  color: inherit;
  white-space: nowrap;
}

.jr-be-sec { display: flex; flex-direction: column; gap: 9px; border-block-start: 1px solid var(--sk-n200); padding-block-start: 14px; }
.jr-be-sec__t { margin: 0; display: flex; align-items: flex-start; gap: 9px; font-family: inherit; font-size: 12.5px; line-height: 1.5; color: var(--sk-n700); }
.jr-be-sec__i { display: inline-flex; color: var(--sk-acc); flex: none; margin-block-start: 2px; }
.jr-be-sec__i svg { inline-size: 15px; block-size: 15px; }

.jr-be-prev > summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding-inline: 14px;
  border: 1px solid var(--sk-n300);
  border-radius: 999px;
  background: var(--sk-card);
  font-family: inherit;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  list-style: none;
  width: fit-content;
}
.jr-be-prev > summary::-webkit-details-marker { display: none; }
.jr-be-prev > summary::after {
  content: "";
  inline-size: 14px;
  block-size: 14px;
  flex: none;
  background: currentColor;
  clip-path: polygon(12% 30%, 50% 68%, 88% 30%, 100% 42%, 50% 92%, 0 42%);
}
.jr-be-prev[open] > summary::after { transform: rotate(180deg); }
.jr-be-prev__box { display: flex; justify-content: flex-start; background: #e5ded7; border-radius: 16px; padding: 14px; margin-block-start: 10px; animation: be-rise .3s ease both; }
.jr-be-prev__bubble {
  max-inline-size: 340px;
  background: var(--sk-card);
  border-radius: 12px 12px 12px 4px;
  box-shadow: var(--sk-sh-sm);
  padding: 12px 13px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
[dir="rtl"] .jr-be-prev__bubble { border-radius: 12px 12px 4px 12px; }
.jr-be-prev__from { font-family: inherit; font-weight: 700; font-size: 11px; color: var(--sk-ok-ink); }
.jr-be-prev__1 { font-family: inherit; font-size: 14px; line-height: 1.5; color: var(--sk-ink); }
.jr-be-prev__2 { font-family: inherit; font-size: 13px; line-height: 1.5; color: var(--sk-n700); }
.jr-be-prev__3 { font-family: inherit; font-size: 11.5px; line-height: 1.4; color: var(--sk-n600); }
.jr-be-prev__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border-block-start: 1px solid var(--sk-n200);
  margin-block-start: 2px;
  padding-block-start: 9px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--sk-ok-ink);
}

.jr-be-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(206px, 1fr)); gap: clamp(12px, 1.8vw, 16px); }
.jr-be-tile { display: flex; flex-direction: column; gap: 8px; border-radius: 16px; background: var(--sk-n100); padding: 14px; }
.jr-be-tile .jr-sk-step__n { inline-size: 26px; block-size: 26px; background: var(--sk-acc); color: #ffffff; font-size: 12.5px; }
.jr-be-tile__t:not([hidden]) { font-family: inherit; font-weight: 600; font-size: 14.5px; line-height: 1.3; letter-spacing: -.01em; }
.jr-be-tile__s { font-family: inherit; font-size: 13px; line-height: 1.5; color: var(--sk-n700); }

.jr-be-dash {
  background: var(--sk-acc100);
  border: 1.5px solid var(--sk-acc);
  border-radius: var(--sk-r-panel);
  padding: clamp(18px, 2.6vw, 30px);
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2vw, 18px);
  animation: be-rise .7s ease .55s both;
}
.jr-be-dash__head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 14px; }
.jr-be-dash__say { display: flex; flex-direction: column; gap: 6px; flex: 1 1 240px; min-width: 0; }
.jr-be-dash .jr-be-sub { color: var(--sk-n800); }
.jr-be-pills { margin: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.jr-be-pill {
  font-family: inherit;
  font-weight: 600;
  font-size: 12.5px;
  line-height: 1.2;
  color: var(--sk-acc700);
  background: var(--sk-card);
  border-radius: 999px;
  padding: 7px 13px;
  white-space: nowrap;
}
.jr-be-warn { margin: 0; display: flex; align-items: flex-start; gap: 9px; font-family: inherit; font-size: 12.5px; line-height: 1.5; color: var(--sk-n700); }
.jr-be-warn__i { display: inline-flex; color: var(--sk-acc); flex: none; margin-block-start: 2px; }
.jr-be-warn__i svg { inline-size: 15px; block-size: 15px; }

.jr-be-end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(12px, 2vw, 20px);
  background: var(--sk-ink);
  color: #ffffff;
  border-radius: var(--sk-r-panel);
  padding: clamp(18px, 2.6vw, 28px);
  animation: be-rise .7s ease .6s both;
}
.jr-be-end__say { display: flex; flex-direction: column; gap: 6px; flex: 1 1 260px; min-width: 0; }
.jr-be-end__t:not([hidden]) { font-family: inherit; font-weight: 700; font-size: clamp(19px, 2.3vw, 25px); line-height: 1.2; letter-spacing: -.025em; }
.jr-be-end__s { font-family: inherit; font-size: 14px; line-height: 1.55; color: rgba(255, 255, 255, .76); max-width: 56ch; }
.jr-be-end__acts { display: flex; flex-wrap: wrap; gap: 10px; }
.jr-be-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 54px;
  padding-inline: 20px;
  border: 1px solid rgba(255, 255, 255, .34);
  border-radius: 999px;
  background: transparent;
  color: #ffffff;
  font-family: inherit;
  font-weight: 600;
  font-size: 14px;
  line-height: 1.25;
  cursor: pointer;
}
.jr-be-ghost:hover { background: rgba(255, 255, 255, .1); }

/* ── Fokus, überall gleich ────────────────────────────────────────────────── */
.jr-sk :focus-visible,
.jr-be :focus-visible { outline: 2px solid var(--sk-acc); outline-offset: 2px; }

/* ── die Bewegungen ───────────────────────────────────────────────────────── */
@keyframes sk-scene { from { opacity: 0; transform: translateY(14px) scale(.99); } }
@keyframes sk-rise { from { opacity: 0; transform: translateY(10px); } }
@keyframes sk-pop { 0% { opacity: 0; transform: scale(.86); } 62% { transform: scale(1.03); } 100% { opacity: 1; transform: none; } }
@keyframes sk-land { 0% { opacity: 0; transform: translateY(-22px) scale(.94); } 64% { transform: translateY(0) scale(1.02); } 100% { opacity: 1; transform: none; } }
@keyframes sk-drawer { from { opacity: 0; transform: translateY(-10px); } }
@keyframes sk-line { from { clip-path: inset(0 0 105% 0); transform: translateY(12px); } to { clip-path: inset(0 0 -12% 0); transform: none; } }
@keyframes sk-snap { 0% { opacity: 0; transform: translate(34px, -26px) scale(.8); } 60% { opacity: 1; } 100% { opacity: 1; transform: none; } }
@keyframes sk-badge { 0% { opacity: 0; transform: scale(.4); } 70% { transform: scale(1.1); } 100% { opacity: 1; transform: none; } }
@keyframes sk-ping { from { transform: scale(.6); opacity: .5; } to { transform: scale(1.9); opacity: 0; } }
@keyframes sk-sheen { 0% { transform: translateX(-60%) skewX(-16deg); } 60%, 100% { transform: translateX(260%) skewX(-16deg); } }
@keyframes pi-slot { 0%, 18% { opacity: 0; } 30%, 74% { opacity: 1; } 100% { opacity: 0; } }
@keyframes pi-ring { 0%, 44% { opacity: 0; transform: translate(-50%, -50%) scale(.72); } 52% { opacity: .85; } 78%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(1.5); } }
@keyframes pi-logo {
  0%, 30% { opacity: 0; transform: translate(-50%, -50%) translateY(-34%) scale(.42) rotate(-9deg); }
  48% { opacity: 1; transform: translate(-50%, -50%) scale(1.06) rotate(2deg); }
  56%, 100% { opacity: 1; transform: translate(-50%, -50%); }
}
@keyframes pi-cta { 0%, 58% { opacity: 0; transform: translateY(9px); } 72%, 100% { opacity: 1; transform: none; } }
@keyframes pi-mark { 0%, 66% { opacity: 0; } 80%, 100% { opacity: 1; } }
@keyframes be-rise { from { opacity: 0; transform: translateY(12px); } }
@keyframes be-line { from { clip-path: inset(0 0 105% 0); transform: translateY(10px); } to { clip-path: inset(0 0 -12% 0); transform: none; } }
@keyframes be-pop { 0% { opacity: 0; transform: scale(.9); } 64% { transform: scale(1.02); } 100% { opacity: 1; transform: none; } }
@keyframes be-order { 0% { opacity: 0; transform: translateY(-26px) scale(.96); } 9%, 82% { opacity: 1; transform: none; } 92% { opacity: 0; transform: translateY(-14px); } 100% { opacity: 0; } }
@keyframes be-badge { 0%, 6% { transform: scale(1); } 12% { transform: scale(1.35); } 20%, 100% { transform: scale(1); } }
@keyframes be-ping { 0% { transform: scale(.6); opacity: .55; } 70% { opacity: 0; } 100% { transform: scale(2.1); opacity: 0; } }
@keyframes be-shift { 0%, 9% { transform: translateY(0); } 16%, 100% { transform: translateY(6px); } }

/* ⭐ «Bewegung ist Dekoration» — bei `reduce` steht alles auf dem Endbild, und
   die drei Stücke, deren Bild 0 ausserhalb der Bühne liegt (die Logo-Landung,
   die eintreffende Bestellung, der Schimmer), bekommen ihre Ruhelage
   ausdrücklich. Ein Standbild aus Bild 0 wäre sonst ein leeres Promo-Bild und
   ein Telefon ohne Bestellung. */
@media (prefers-reduced-motion: reduce) {
  .jr-sk *, .jr-sk *::before, .jr-sk *::after,
  .jr-be *, .jr-be *::before, .jr-be *::after {
    animation: none !important;
    transition: none !important;
  }
  .jr-sk-promo__logo { opacity: 1; transform: translate(-50%, -50%); }
  .jr-sk-promo__cta { opacity: 1; transform: none; }
  .jr-sk-promo__mark { opacity: 1; }
  .jr-sk-promo__slot, .jr-sk-promo__ring { opacity: 0; }
  .jr-sk-tall__sheen { opacity: 0; }
  .jr-be-order { opacity: 1; transform: none; }
  .jr-be-list { transform: none; }
  .jr-sk-intro__t, .jr-sk-intro__s, .jr-be-h1 { clip-path: none; }
  .jr-sk-ava--ping::after, .jr-sk-fin__mark::after, .jr-be-phone__ping { opacity: 0; }
}

/* ── STARTKLAR · Nachtrag 01.09.2026 ─────────────────────────────────────────
   🔴 VIER KLASSEN OHNE REGEL, von `journey_view_gate` gefunden, bevor sie ein
   Mensch sehen konnte. Die Lehre der Bauregel «jede gezeichnete Klasse hat eine
   Regel» ist genau diese: eine Beschriftung ohne Regel erbt 16 px und fällt
   niemandem auf, bis sie neben einer 13-px-Zeile steht.
   ⚠️ `.jr-sk-scene--<id>` wurde stattdessen aus dem Markup ENTFERNT: sie war
   eine Klasse ohne Zweck, und eine tote Klasse ist schlechter als eine fehlende
   Regel — sie sieht nach Absicht aus. */
.jr-sk-btn__t {
  font-family: inherit;
  font-weight: inherit;
  font-size: inherit;
  line-height: 1.25;
  white-space: nowrap;
}
/* Die QR-Schublade stellt das Bild neben den Text statt in ein `auto-fit`-
   Raster: der Code hat eine feste Grösse und soll nicht mitwachsen. */
.jr-sk-drawer__body--qr { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
/* Google: die eingerastete Zeile ist EINE Zeile mit dem Haken am Ende, nicht
   zwei übereinander wie im Instagram-Profil. */
.jr-sk-snap--ok { flex-direction: row; align-items: center; }

/* `.jr-sk-fin__t` ist ein `<h1>` (jede Station trägt genau eine Überschrift —
   im geführten Zustand die Einleitung, im fertigen Kasten das Finale). Ein h1
   bringt seinen eigenen Aussenabstand mit; das Flex-Gerüst darum setzt die
   Abstände, also wird er hier auf null gestellt. */
.jr-sk-fin__t { margin: 0; }

/* ── STARTKLAR · die Leiste und der Einwilligungsbanner ──────────────────────
   🔴 GEMESSEN IN EINEM ECHTEN BROWSER, OHNE SKRIPT: der Banner ist
   `position: fixed; bottom: 0; z-index: 1000` und wird serverseitig gerendert.
   `body.cookie-banner-visible` — die Marke, an der `.jr-foot` seit dem
   24.08.2026 hängt — setzt aber JAVASCRIPT. Ohne Skript bleibt sie aus, die
   Hebung greift nicht, und eine `bottom: 0`-Leiste steht UNTER dem Banner.
   Playwright hat den Klick genau deshalb verweigert: «gz-banner__in subtree
   intercepts pointer events».

   ⇒ SOLANGE DER BANNER OFFEN IST, KLEBT DIESE LEISTE NICHT. Sie steht dann am
   Ende des Inhalts und ist durch Scrollen immer erreichbar — ohne dass hier
   irgendeine Bannerhöhe geraten werden müsste (die hängt an Sprache und
   Breite). Sobald der Wirt geantwortet hat, trägt der Banner `hidden`, die
   Bedingung fällt weg und die Leiste klebt wieder.
   ⭐ `[hidden]` IST DER VERLÄSSLICHE SCHALTER, weil ihn BEIDE Seiten setzen:
   der Server, wenn schon eine Entscheidung gespeichert ist
   (lp_trial/consent_banner.php), und gz-consent.js, wenn sie gerade fällt.
   ⚠️ `.jr-foot` hat dieselbe Lücke und behält sie hier — sie zu schliessen
   hiesse jede andere Station anzufassen. Gemeldet, nicht mitgemacht. */
body:has(.gz-banner:not([hidden])) .jr-sk-bar { position: static; }

/* ── STARTKLAR · der Name steht EINMAL ──────────────────────────────────────
   🔬 IM BROWSER GEMESSEN, nicht überlegt: der Reise-Streifen über der Karte
   nennt die Station («Station · Startklar»), und der Kopf der Karte nennt sie
   noch einmal — zwei Zentimeter darunter, in beiden Sprachen, auf allen drei
   Breiten. Der Entwurf sieht genau EINEN grossen Namen vor.
   ⇒ Für diese zwei Stationen weicht die Chrome, nicht der Entwurf: der
   Namensblock des Streifens verschwindet, die PFEILE bleiben — sie sind die
   einzige Möglichkeit, ohne Fussknopf vor- und zurückzugehen, und sie tragen
   ihre eigenen `aria-label`.
   ⛔ NUR DIESE ZWEI. `body.jr-page[data-jr-station="…"]` ist derselbe Griff, mit
   dem `menue_upload` seit dem 30.08.2026 seine Chrome anpasst (Z. 6995). */
body.jr-page[data-jr-station="launch_station"] .jr-nav__where,
body.jr-page[data-jr-station="bestellungen_empfangen"] .jr-nav__where { display: none; }

/* ── STARTKLAR · «Mehr dazu» — das Erklärvideo des Inhabers ──────────────────
   01.09.2026 · OWNER: «هي روابط تحطه بمكان مناسب تحت كلمة للمزيد باخر سطر كل جملة»

   Ein Link als LETZTE ZEILE des Anleitungsblocks, unter dem Satz, den er
   erklärt. Fünf Werkzeuge haben eines; der QR-Code nicht — er ist das einzige,
   das die Plattform dem Wirt vollständig abnimmt.

   ⛔ DAS PLAY-ZEICHEN KOMMT AUS DEM STYLESHEET, NICHT AUS DEM MARKUP.
   `public-i18n.js` schreibt `textContent` für jedes `[data-i18n]` — ein `<svg>`
   oder ein Zeichen IM Link wäre in dem Augenblick weg, in dem das Bündel
   eintrifft. Ein `::before` ist kein Kindknoten und überlebt.
   ⚠️ Und es wird unter RTL NICHT gespiegelt: das Play-Dreieck ist ein Symbol
   für «abspielen», keine Richtungsangabe — dieselbe Unterscheidung, die
   `[dir="rtl"] svg[data-jr-flip]` seit n12-Gate D7 trifft. */
.jr-sk-more { margin: 0; }
.jr-sk-more__a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13px;
  line-height: 1.4;
  color: var(--sk-acc700);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.jr-sk-more__a:hover { color: var(--sk-acc); }
.jr-sk-more__a::before {
  content: "";
  inline-size: 15px;
  block-size: 15px;
  flex: none;
  background: currentColor;
  /* ein Abspiel-Dreieck, aus EINEM Element. Die erste Fassung baute es aus
     einem Kreis plus einem Rahmen-Dreieck mit negativem Aussenabstand — drei
     Werte, die sich bei jeder Schriftgrösse neu finden müssen. */
  clip-path: polygon(18% 6%, 18% 94%, 94% 50%);
}
/* ⛔ NICHT SPIEGELN: ein Abspiel-Dreieck ist ein Symbol für «abspielen», keine
   Richtungsangabe — dieselbe Unterscheidung, die `svg[data-jr-flip]` trifft. */

/* ══════════════════════════════════════════════════════════════════════════
   ANMELDEZEITRAUM auf der Anmeldeseite (07.09.2026, Fassung nach der Prüfrunde)
   ══════════════════════════════════════════════════════════════════════════
   Dieselben Klassen wie auf der Anzeigenseite (includes/lp_trial/
   promo_countdown.php rendert beide), aber die Anmeldeseite lädt NUR
   journey.css — deshalb steht die Variante `entry` hier und nirgends sonst.

   ⚖️ RUHENDE AUSSAGE, KEINE UHR. Auf DIESER Seite füllt jemand gerade sechzehn
   Felder aus; ein tickender Zähler über dem Formular wäre Druck auf jemanden,
   der die Entscheidung längst getroffen hat. Es steht hier, was gilt: bis wann
   die Anmeldung offen ist — und dass eine Verlängerung möglich, aber nicht
   zugesagt ist.
   ⛔ Der Vorbehalt wird bei KEINER Breite ausgeblendet.
   ────────────────────────────────────────────────────────────────────────── */
.lp-promo--entry {
  margin-block: 14px 2px;
  padding: 10px 12px;
  border: 1px solid var(--jr-accent-line);
  border-radius: var(--jr-radius-sm);
  background: var(--jr-accent-tint);
}
.lp-promo--entry .lp-promo__window {
  display: block;
  font-size: 13.5px; font-weight: 700; line-height: 1.4;
  color: var(--jr-accent-ink);
}
.lp-promo--entry .lp-promo__extend {
  display: block; margin-block-start: 2px;
  font-size: 12.5px; font-weight: 500; line-height: 1.5;
  color: var(--jr-muted);
}
.lp-promo--entry .lp-promo__ended { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--jr-muted) }
.lp-promo--entry .lp-promo__ended-t { color: var(--jr-ink) }
[dir="rtl"] .lp-promo--entry .lp-promo__window,
[dir="rtl"] .lp-promo--entry .lp-promo__extend { letter-spacing: 0; line-height: 1.85 }
/* Ein Ausdruck ist ein Beleg: die Bedingung bleibt darauf richtig. */
@media print {
  .lp-promo--entry { border: 0; background: none; padding: 0 }
}

/* ══════════════════════════════════════════════════════════════════════════
   GOOGLE-3 · Station 18 «google_praesenz» — helle Karten (12.09.2026)
   ══════════════════════════════════════════════════════════════════════════
   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3. Nur Klassen `jr-gp-*`
   und Nachfahren von `.jr-gp-note` — keine bestehende Regel wird umgebogen.
   ────────────────────────────────────────────────────────────────────────── */

/* G3-UX-02 · `.jr-be-ghost` ist WEISS AUF DURCHSICHTIG — gebaut für die dunkle
   `.jr-be-end`-Leiste. Auf einer weissen `.jr-sk-card`/`.jr-be-row` war jeder
   Zweitknopf unsichtbar (Prüfen, Zurück, Zugriff anfragen, Verbinden).
   ⇒ `.jr-gp-ghost` für helle Flächen; `.jr-be-ghost` bleibt NUR in `.jr-be-end`.
   ⚖️ GEMESSEN: Rand `--sk-n600` (#7d7979) auf #ffffff ≈ 4,3:1 — über der
   3:1-Schwelle für Bedienelemente (WCAG 1.4.11); `--sk-n500` läge bei ≈ 2,9:1
   darunter, `--sk-n300` weit darunter. Schrift `--sk-ink` auf #ffffff ≈ 16:1.
   Grösse und Rundung wie `.jr-be-ghost`; `align-self` hält den Knopf in der
   Spaltenzeile `.jr-be-row` auf Inhaltsbreite. */
.jr-gp-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-start;
  gap: 8px;
  min-height: 54px;
  max-width: 100%;
  padding-inline: 20px;
  border: 1px solid var(--sk-n600);
  border-radius: 999px;
  background: transparent;
  color: var(--sk-ink);
  font-family: inherit;
  font-weight: 600;
  font-size: 14px;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.jr-gp-ghost:hover { background: var(--sk-n100); }
.jr-gp-ghost:focus-visible { outline: 2px solid var(--sk-acc); outline-offset: 2px; }

/* G3-UX-06 · der Art.-13-Hinweis dieser Station. Die Regeln und `--mu-*`-Tokens
   des Menü-Hinweises gelten nur auf `menue_upload` — hier fiel die Karte auf das
   nackte `.jr-card` zurück (1,5-px-Rand, kein Grund, Link ohne Akzent, weil
   `--mu-a700` hier nicht existiert).
   ⛔ Der Link bleibt GESCHWISTER des Satzes (Hydrierung, N9) — die Kinder tragen
   weiter `jr-mu-note__*`; nur ihre Farben und Grössen werden hier gesetzt. */
.jr-be .jr-card.jr-gp-note {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  padding: 13px 14px;
  border: 0;
  border-radius: 14px;
  background: var(--sk-n100);
}
.jr-gp-note .jr-mu-note__icon { color: var(--sk-n600); }
.jr-gp-note .jr-card__text { margin: 0; font-size: 13px; line-height: 1.55; color: var(--sk-n800); }
.jr-gp-note .jr-mu-note__link { font-size: 13px; line-height: 1.55; color: var(--sk-acc700); }

/* G3-UX-07 · der Prüfstatus. Vorher `.jr-be-ok` (Checkbox-Etikett, 13,5 px,
   `cursor: pointer`) gegen `.jr-be-warn` (12,5 px, heller, ohne Zeichen) — die
   Warnung war die leiseste Zeile der Karte. Jetzt EINE Grösse für beide, getönter
   Grund wie `.jr-be-banner`, ein Zeichen, kein Zeiger.
   ⛔ Zustand nie nur über Farbe: der Satz und das Zeichen tragen ihn. */
.jr-gp-vom {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  border-radius: 14px;
  padding: 11px 13px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.45;
  cursor: default;
}
.jr-gp-vom--ok { background: var(--sk-ok-soft); color: var(--sk-ok-deep); }
.jr-gp-vom--warn { background: var(--jr-amber-soft); color: var(--jr-amber-ink); }
.jr-gp-vom__i { inline-size: 24px; block-size: 24px; border-radius: 999px; display: grid; place-items: center; flex: none; background: currentColor; }
.jr-gp-vom__i svg { inline-size: 13px; block-size: 13px; stroke: #ffffff; }

/* G3R2-MAPS · der Maps-Link der Bestätigungskarte. Er trug `jr-mu-note__link`,
   dessen Farbe `var(--mu-a700)` nur auf `menue_upload` existiert — hier fiel er
   auf die Absatzfarbe zurück und war nur noch am Unterstrich als Link zu erkennen.
   ⇒ eigene Klasse `jr-gp-link`, derselbe Akzent wie der Art.-13-Link dieser
   Station (`--sk-acc700` #ae1800, definiert auf `.jr-sk, .jr-be`).
   ⚖️ GERECHNET: #ae1800 auf #ffffff ≈ 7,2:1 (WCAG 1.4.3 verlangt 4,5:1).
   ⛔ Der Unterstrich bleibt — ein Link nie nur über Farbe (WCAG 1.4.1); der
   Abstand 3px ist derselbe wie vorher unter `jr-mu-note__link`. */
.jr-be .jr-gp-link { color: var(--sk-acc700); text-decoration: underline; text-underline-offset: 3px; }



/* ══════════════════════════════════════════════════════════════════════════
   19.09.2026 · OWNER — «النموذج يفهم انه لما يولد الشعار يكون الوانه فاتحة —
   هو رح يركب على خلفيات غامقة»
   ══════════════════════════════════════════════════════════════════════════
   The generator now draws LIGHT marks (logo_prompt_builder.php, «Placement
   requirement»). Every surface above that shows a logo was white or
   `--jr-quiet` (#f7f9fd) with a pale checkerboard — a white mark on it is an
   empty field, and the owner would be choosing a proposal they cannot see.
   ⇒ The logo is shown WHERE IT WILL LIVE: on a dark surface. The checkerboard
   stays (transparency is still the point of this station), in dark squares.
   Covers the proposal card, the proposal slots, the stored-logo thumbnail
   (logo + review screens) and the zoom dialog.
   ⛔ NOT the picked-file preview (`.jr-logo-picked__img`): that is "the file you
   chose", shown before anything was uploaded, not the logo in place.
   ⚠️ AM DATEIENDE GESCHRIEBEN, wie jeder Block seit D3 — it wins by order over
   the three original declarations, which stay untouched. */
.jr-logo-slot { background: #171c33; border-color: #2a3150; }
.jr-logo-offer__img,
.jr-logo-slot__img,
.jr-logo-have__img,
.jr-logo-dialog__image-wrap {
  background-color: #171c33;
  background-image:
    linear-gradient(45deg, #202644 25%, transparent 25%, transparent 75%, #202644 75%),
    linear-gradient(45deg, #202644 25%, transparent 25%, transparent 75%, #202644 75%);
  background-size: 12px 12px;
  background-position: 0 0, 6px 6px;
}
.jr-logo-dialog__image-wrap { background-size: 20px 20px; background-position: 0 0, 10px 10px; border-color: #2a3150; }
/* the hover used the `background` SHORTHAND and would wipe the dark surface */
.jr-logo-have__zoom:hover .jr-logo-have__img { background-color: #232a4a; }
