/* ==========================================================================
   Restaurang Moldau, page-level composition.
   Loaded after styles.css. Nothing here restates a token.
   Sections:
     1. Hero
     2. Hungerväljaren (the portion selector)
     3. Ettstjärniga hallen (the one-star hall)
     4. Galleries and Instagram
     5. Hitta hit
     6. Menu page
     7. Historien
     8. Text pages
   ========================================================================== */

/* 1. Hero: the medallion ================================================ */
/* After the art director's folder cover: a circular plate on cream, the
   wordmark reversed inside it, the flag and an Almdudler bottle overlapping the
   rim, and the We-are-schnitzel badge pinned to the corner.
   The video lives inside the circle and keeps the .hero__media and .hero__video
   hooks, so hero.js and its reduced-motion and metered-connection rules work
   unchanged. */

/* No photograph behind this band, by decision. The medallion is the picture; the
   cream is the paper it sits on, exactly as on the folder cover. The outline
   button therefore keeps the shared .knapp--linje treatment, because on a known
   cream it can take its contrast from the ink. */
.hero {
  background: var(--papper);
  padding-block: var(--s-7) var(--s-8);
}

.medaljong {
  position: relative;
  width: min(41rem, 100%);
  margin-inline: auto;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  text-align: center;
}

.medaljong__foto {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
}

.medaljong__foto img,
.medaljong__foto video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 45%;
}

/* The poster sits under the video and fades out once frames run. */
.medaljong__foto img { z-index: 0; transition: opacity 600ms ease; }
.medaljong__foto video { z-index: 1; }

/* Not decoration: this is the contrast floor. At 0.72 the worst the footage can
   put behind the type is a fully white frame rendering as rgb(88,83,80), which
   holds cream at 6.45:1. Measured against the frame, because a moving picture
   cannot be sampled: the veil is what makes the number knowable. */
.medaljong__sloja {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: radial-gradient(circle at 50% 42%,
    rgb(23 16 12 / 0.72) 0%, rgb(23 16 12 / 0.72) 58%, rgb(23 16 12 / 0.88) 100%);
}

.medaljong__ring {
  position: absolute;
  inset: var(--s-4);
  border-radius: 50%;
  border: 1px solid rgb(232 200 106 / 0.55);
  z-index: 3;
}

.medaljong__inner {
  position: relative;
  z-index: 4;
  color: var(--papper);
  padding-inline: clamp(1.5rem, 8%, 4rem);
}

/* Gold never sits on the footage: over any workable veil it tops out at 4.5:1
   and collapses to 1.06:1 on a bright frame. On the medallion the ink is cream;
   gold stays on the solid grounds. */
.medaljong__halsning {
  color: var(--papper);
  font-size: clamp(1.4rem, 3.4vw, 2.1rem);
  transform: none;
  margin: 0;
}

.medaljong__inner .ordmark__bild {
  width: min(13rem, 52%);
  margin: var(--s-1) auto var(--s-2);
}

.medaljong__krok {
  color: var(--papper);
  text-wrap: balance;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(0.95rem, 2.3vw, 1.45rem);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  line-height: 1.25;
  margin: 0;
}

.medaljong__tagline {
  color: var(--papper);
  margin-top: var(--s-3);
}

.medaljong__badge,
.medaljong__flagga,
.medaljong__flaska {
  position: absolute;
  z-index: 5;
  height: auto;
}

/* Placed against the circle, not against its square box. Corner offsets put the
   badge 38.5px and the bottle 33px clear of the rim in cream, so the hero read
   as a disc with two stickers parked beside it. The flag only worked because it
   is wide and sits where the curve is shallow. These land each centre on the rim
   so every ornament straddles it, which is what the flag was already doing. */
.medaljong__badge  { width: clamp(4.6rem, 13%, 7rem);
                     left: 88.3%; top: 17.9%; translate: -50% -50%; }
.medaljong__flagga { width: clamp(6rem, 19%, 10rem);
                     left: 22%; top: 12%; translate: -50% -50%; rotate: -8deg; }
.medaljong__flaska { width: clamp(2.6rem, 7%, 4rem);
                     left: 9%; top: 78.7%; translate: -50% -50%; rotate: -7deg; }

/* Every ornament hangs outside its frame, which is the point of a collage and
   also horizontal scroll on a narrow screen. On small screens they tuck in. */
/* 44rem, not 46rem: the medallion is min(41rem, 100%) inside a column of
   min(100% - 3rem, 74rem), so it stops growing at 41rem + 2 * --s-5 = 44rem.
   At 46rem the ornaments were still at mobile size on an already full-size
   medallion, and jumped 40% at the boundary. */
@media (max-width: 44rem) {
  .medaljong__flagga { width: 5.5rem; left: 20%; top: 10%; }
  .medaljong__flaska { width: 2.4rem; left: 8%; }
  .medaljong__badge  { width: 4.2rem; left: 89%; top: 16%; }
}

.knapp-rad--mitt { justify-content: center; margin-top: var(--s-6); }

.hero__ort {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-vid);
  color: var(--guld-ljus);
  margin: 0 0 var(--s-4);
}

/* 2. Hungerväljaren ===================================================== */

.hunger__rutnat {
  display: grid;
  gap: var(--s-7);
  align-items: center;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 52rem) {
  .hunger__rutnat { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
}

/* From 72rem the dishes get a column of their own on the right, in the empty
   ground beside the slider. Measured at 1440: the slider and its chips are capped
   at 26rem and end at x944 while the column runs to x1312, so 368px sat empty
   while the photographs queued up underneath.
   A real grid column rather than absolute placement, because the escalating line
   above spans the full width of the middle column and its length changes with the
   portion — the browser should be the thing that guarantees they never meet. */
@media (min-width: 72rem) {
  .hunger__rutnat {
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr) minmax(0, 20rem);
    align-items: start;
  }
}

.hunger__portratt { position: relative; }

.hunger__portratt .ram__inre { aspect-ratio: 1; }

/* The photograph swaps with the selected portion. Only the active one is in
   the accessibility tree; the rest are removed, not merely hidden visually. */
.hunger__bild { display: none; width: 100%; height: 100%; object-fit: cover; }
.hunger__bild[data-aktiv="true"] { display: block; }

.hunger__vikt {
  font-family: var(--f-display);
  font-weight: 300;
  font-size: clamp(3.5rem, 2rem + 8vw, 7rem);
  line-height: 0.9;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--guld);
}

.hunger__vikt sub {
  font-size: 0.22em;
  letter-spacing: var(--spar-vid);
  vertical-align: baseline;
  margin-left: 0.3em;
  bottom: 0;
}

.hunger__namn {
  font-family: var(--f-display);
  font-size: var(--t-lg);
  text-transform: uppercase;
  letter-spacing: var(--spar-vid);
  margin: var(--s-2) 0 var(--s-4);
  color: var(--papper);
}

.hunger__replik {
  font-family: var(--f-hand);
  font-size: clamp(1.375rem, 1rem + 1.4vw, 1.875rem);
  line-height: 1.25;
  color: var(--guld-ljus);
  min-height: 3.6em;
  margin: 0 0 var(--s-5);
}

/* All four repliker share one grid cell, so the cell is as tall as the LONGEST
   of them at whatever width the page is. That is what stops the hero jumping
   when the guest drags -- a fixed em reserve cannot know how many lines a
   sentence takes at a given width, and measured on HEAD it was still moving 26
   and 37px. visibility rather than display so the hidden three keep taking up
   their space, and so they stay out of the accessibility tree. */
.hunger__replik { display: grid; }

.hunger__replik-grupp {
  grid-area: 1 / 1;
  visibility: hidden;
}

.hunger__replik-grupp[data-aktiv="true"] { visibility: visible; }

/* Two lines, and the break is the joke: the guest is read on the first, Moldau
   answers on the second. Run together as one sentence the turn between them was
   a full stop in the middle of a line, which is where it stops being a turn.
   `display: block` is not optional on a span you are giving line behaviour --
   the playbook has three separate bugs from exactly that omission. */
.hunger__replik-rad { display: block; }

/* The answer sits back a step. Not with opacity, which takes the contrast down
   with it -- a named colour, so the ratio is a number we can state: cream on
   walnut rather than the light gold above it. */
.hunger__replik-rad--svar { color: var(--papper); }

/* Own track, not accent-color. accent-color paints the fill and the thumb but
   leaves the UA groove, which on this walnut band renders as a near-white bar at
   low values — a colour that is not in the palette — and as a fully red bar at
   the top, so four discrete portions read as a progress meter. */
.hunger__reglage {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  max-width: 26rem;
  margin: 0 0 var(--s-4);
  /* --tumme-skala scales the control's own hit box and the thumb together
     (hunger.js reads it back to size --tumme) -- see the comment by --tumme
     below for why they have to move as one number. 1 on desktop, bigger on
     mobile where the slider is the only way left to change portion. */
  --tumme-skala: 1;
  height: calc(var(--tapp) * var(--tumme-skala));
  background: transparent;
}

.hunger__reglage::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: rgb(245 239 228 / 0.22);
}

.hunger__reglage::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: rgb(245 239 228 / 0.22);
}

/* The thumb IS the schnitzel, and it grows as you pull right. Dennis
   2026-08-13, and it says what the block says without a word of copy.

   The picture is cut out of the restaurant's own portion photograph by
   tools/bygg_schnitzelmarke.py -- their food, so there is nothing to answer
   for. A drawn one was tried first and read as a potato at every size until it
   was given a plate; the photograph needs no plate, because the breading and
   the lemon carry the shape on their own.

   --tumme is the width, written by hunger.js per portion, and everything else
   follows it: the height from the cut-out's own proportion, and the top margin
   so the schnitzel stays centred on the 4px track however big it is. Three
   properties animate together, which is why they are all derived from one
   number instead of set separately. */
.hunger__reglage {
  --tumme: 22px;
  --tumme-h: calc(var(--tumme) / 0.947);   /* the cut-out's width/height */
}

.hunger__reglage::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--tumme);
  height: var(--tumme-h);
  margin-top: calc((4px - var(--tumme-h)) / 2);
  border: 0;
  border-radius: 0;
  background: url(img/tumme-schnitzel.webp) no-repeat center / contain;
  cursor: pointer;
  transition: width 200ms linear, height 200ms linear, margin-top 200ms linear;
}

.hunger__reglage::-moz-range-thumb {
  width: var(--tumme);
  height: var(--tumme-h);
  border: 0;
  border-radius: 0;
  background: url(img/tumme-schnitzel.webp) no-repeat center / contain;
  cursor: pointer;
  transition: width 200ms linear, height 200ms linear;
}

@media (prefers-reduced-motion: reduce) {
  .hunger__reglage::-webkit-slider-thumb { transition: none; }
  .hunger__reglage::-moz-range-thumb { transition: none; }
}

.hunger__steg {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* "Lilla Moldau" wraps to two lines, so without this its button is 54px and
     the other three are 44px, giving the row a ragged bottom edge. */
  grid-auto-rows: 1fr;
  gap: var(--s-2);
  max-width: 26rem;
  list-style: none;
  margin: 0 0 var(--s-5);
  padding: 0;
}

.hunger__steg button {
  width: 100%;
  /* The li stretches to the tallest row, the BUTTON did not: "Lilla Moldau"
     wraps to two lines and measured 54px against 44px for the other three, so
     three of the four boxes floated inside their own cell. grid-auto-rows on
     the list is only half the fix. */
  height: 100%;
  min-height: 2.75rem;
  background: none;
  border: 1px solid rgb(245 239 228 / 0.35);
  color: var(--papper);
  font-family: var(--f-display);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  padding: var(--s-2);
}

.hunger__steg button[aria-pressed="true"] {
  background: var(--guld);
  border-color: var(--guld);
  color: var(--valnot);
}

.hunger__pris {
  font-size: var(--t-sm);
  color: var(--papper);
  opacity: 0.85;
  margin: 0;
}

/* Without JavaScript the four portions are simply listed. */
.hunger__interaktiv { display: none; }
.hunger__statisk { display: block; }

html[data-js="true"] .hunger__interaktiv { display: block; }
html[data-js="true"] .hunger__statisk { display: none; }

.hunger__statisk dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2) var(--s-5);
  margin: 0;
  font-family: var(--f-display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.hunger__statisk dt { color: var(--guld); }
.hunger__statisk dd { margin: 0; }

/* The four portions as a plain pair list, centred, on the menu page hero. */
/* start, not center: the eyebrow, the display heading and the lead are all
   flush to the gutter, so a centred list was the one unplaced thing in the
   band. dt stays right-aligned, which is the detail worth keeping. */
.portionslista {
  justify-content: start;
  display: grid;
  grid-template-columns: auto auto;
  gap: var(--s-2) var(--s-5);
  justify-content: center;
  margin: var(--s-6) 0 0;
  font-family: var(--f-display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: var(--t-sm);
}

.portionslista dt { color: var(--guld); text-align: right; }
.portionslista dd { margin: 0; text-align: left; }

/* 3. Ettstjärniga hallen ================================================ */

/* OMBYGGD 2026-08-11 efter Dennis beskrivning: de två ytterligheterna mot
   varandra i mitten, deras egen siffra under, och en fråga i botten som gör
   blocket till en inbjudan.

   Spegeln mot Kenar är borttagen tillsammans med formen den speglade. Ett
   centrerat block har ingen sida att spegla, och att behålla rutnätet för att
   det var nytt hade varit att spara mekanik utan uppgift. */
/* Centred since 2026-08-12, when the quoted reviews left and the block became a
   single column: heading, figure, invitation, button. Ranged left it was the only
   thing in the band not on the centre line, and with nothing beside it the
   asymmetry read as a mistake rather than as a column start. */
.hallen__topp { max-width: 44rem; margin-inline: auto; text-align: center; }
.hallen__topp h2 { hyphens: manual; }

/* DISPLAYRUBRIKEN ÄR BORTA sedan 2026-08-17 och ögonbrynet är h2 i dess ställe.
   .ogonbryn bär margin-bottom var(--s-3), vilket är rätt när den rubricerar en
   rubrik under sig -- här finns ingen, och sömmen mot .hallen__fakta bär redan
   avståndet. Utan nollan står 12 px luft i en söm som just krympts. */
.hallen__rubrik { margin: 0; }

.hallen__extremer {
  margin-top: var(--s-7);
  display: grid;
  gap: var(--s-6);
  /* start, inte stretch: de två sidorna har olika många rader text, och en
     sträckt kolumn ger en tom guldram i botten på den kortare. Samma skäl som
     .hallen__rutnat redan bär en notis om. */
  align-items: start;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 52rem) {
  .hallen__extremer { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-7); }
}
.hallen__sida { display: grid; gap: var(--s-5); align-content: start; }

/* Stjärnraden som rubricerar sin sida. role="img" med aria-label bär den för
   skärmläsare, så tecknen själva är aria-hidden -- fem stjärntecken lästa upp
   som text är fem ord ingen bad om. */
.hallen__rad { margin: 0; font-size: var(--t-lg); letter-spacing: 0.14em; }

/* Stjärnfärgerna är avstämda mot VALNÖT, och blocket stod på tidningspapper när de
   rättades. Grinden mätte då 1,65:1 för guldet och 2,44:1 för det ljusa rödet mot
   kravet 3:1, alltså är de här raderna en rättelse och inte en smaksak. Marken är
   papperdjup sedan 2026-08-18 (Dennis bytte plats på omdömena och Instagram), och
   den är LJUSARE -- de mörka valen blev alltså bara säkrare, 1,90:1 respektive
   2,79:1 för de ljusa som fortfarande inte får användas. Samma val sajten redan gör
   i .recension--bra, som ligger på creme och därför bär --guld-mork. */
.hallen .hallen__rad.stjarnor--fem { color: var(--guld-mork); }
.hallen .hallen__rad.stjarnor--ett { color: var(--rod-djup); }

/* --- deras egen siffra ------------------------------------------------- */

/* SÖMMEN ÄR KRYMPT, 2026-08-17. Den var margin-top s-8 (64) + padding-top s-6
   (32) = 96 px runt en linje, mätt fram när en displayrubrik stod ovanför och
   skulle hållas ifrån talen. Ovanför står nu ett ögonbryn på 19 px, och 96 px
   luft omkring en etikett läser som att något saknas mellan dem -- vilket det
   också gör. s-5 + s-5 = 48. Linjen behålls: den skiljer husets etikett från
   Googles tal, och det är den enda gränsen i blocket som betyder något. */
.hallen__fakta {
  margin-top: var(--s-5);
  padding-top: var(--s-5);
  /* Mörk linje, inte ljus: bandet är en ljus mark -- tidningspapper när linjen
     skrevs, papperdjup sedan 2026-08-18 -- och en ljus linje på creme är ingen
     linje. Valnöt på 20 % håller på båda. */
  border-top: 1px solid rgb(43 26 14 / 0.20);
  text-align: center;
}
/* --- Googles egen statistik ------------------------------------------- */
/* Guld på blockets mark får bara vara --guld-mork -- den var tidningspapper och är
   papperdjup sedan 2026-08-18, och det ljusa guldet faller på båda (1,65:1
   respektive 1,28:1). Regeln gäller en ritad form precis som en textrad. */

/* Snittet: talet stort till vänster, stjärnorna och underlaget till höger.
   Baslinjen är inte centrum -- 4,6 i 6,5rem mot en rad på 1,2rem centrerade
   till en stjärnrad som svävade mitt på siffran. Stjärnorna ligger mot talets
   överkant och texten under dem. */
.hallen__snitt {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-3) var(--s-5);
  text-align: left;
}

/* SNITTET OCH STAPLARNA PÅ EN RAD, 2026-08-17: blockets största vertikala vinst.
   Staplade mätte de 104 + 32 + 144 = 280 px; som en rad är höjden den högsta av
   dem, alltså 144. Ingenting krympte -- 4,6 står i samma grad, staplarna har
   samma tal.

   RADEN ÄR FLEX, INTE GRID, och det är en rättelse grinden tvingade fram. Först
   stod den som `grid-template-columns: auto auto`. En auto-kolumn mäts på sitt
   innehåll, och histogrammets innehåll är procentbreda staplar i ett spår på
   minmax(0, 1fr) -- alltså har det ingen egen bredd att mäta. Kolumnen föll till
   105 px, och DÅ BLEV ETTORNAS STAPEL 0,0 px: 57 av 2 477 är 2,3 %, och 2,3 % av
   ingenting är ingenting. Blocket slutade visa det som är hela dess påstående,
   utan att något såg trasigt ut -- fem rader med rätt tal stod kvar. Det var
   grindens första körning som hittade det.

   Med flex bär histogrammet sin egen bredd (flex-basis 30rem) i stället för att
   ärva den ur en kolumn som frågar det om samma sak. Snittet får flex: none --
   ett flex-barn krymper i tysthet, och det här barnet är ett tal i displaygrad
   som inte får radbrytas till 4, / 6. Ryms de inte bryter raden i stället, och
   grinden mäter vilket läge som faktiskt gäller.

   Brytpunkten är 52rem, samma som resten av blocket redan använder. Under den
   faller de tillbaka i stapel: 4,6 i clamp(3.2rem, 11vw, 6.5rem) plus fem
   staplar med tal går inte i bredd på en telefon. */
.hallen__jamn {
  display: grid;
  gap: var(--s-6);
  justify-items: center;
}
@media (min-width: 52rem) {
  .hallen__jamn {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--s-7);
  }
  .hallen__jamn > .hallen__snitt { flex: none; }
  /* flex: 1 1 20rem, inte 0 1 30rem. Med basis 30rem RADBRÖT raden vid 832 och
     833 px -- flex-wrap wrappar hellre än krymper, så media-frågan sa "rad" medan
     skärmen visade stapel, och blocket var 797 px där. Grinden fällde exakt de
     två vyerna; brytpunkten är bara prövad på sina egna kanter.
     Basis 20rem ryms i spalten redan vid 52rem, grow tar resten upp till taket.
     max-width behövs för att grow annars sväljer hela överskottet på 1920 och
     staplarna blir bredare än de 30rem de mättes för. */
  .hallen__jamn > .hallen__histogram { flex: 1 1 20rem; max-width: 30rem; }
}

.hallen__snitt-hoger { display: grid; gap: var(--s-2); }

.hallen__snitt-hoger { justify-items: center; text-align: center; }

/* Antalet är blockets ingång: egen rad tvärs över hela bredden, ovanför snittet,
   i displaysnittets grader. Det stod först under stjärnorna som en fotnot och
   sedan över dem inne i högerkolumnen; Dennis ritade ut var det hör hemma. Guld,
   inte valnöt, för att hålla ihop med talet under -- och --guld-mork, eftersom
   ljust guld mäter 1,28:1 på blockets mark (1,65:1 på tidningspappret det stod på
   före 2026-08-18). Mörkt guld mäter 5,49:1 här. */
.hallen__antal {
  margin: 0 0 var(--s-5);
  font-family: var(--f-display);
  font-weight: 300;
  font-size: var(--t-xl);
  letter-spacing: 0.02em;
  color: var(--guld-mork);
  text-align: center;
}

.hallen__betyg { margin: 0; color: var(--guld-mork); }

/* Fem stjärnor två gånger: den undre i konturform, den övre klippt till andelen.
   Ett klipp renderar vilket snitt som helst, och det finns en form att hålla rätt
   på i stället för tre. overflow: hidden på den fyllda raden, inte en mask: en
   mask på ett flex-barn som redan bär SVG:er blev en tredje ritad sak att felsöka
   för samma resultat. */
.hallen__stjarnor {
  position: relative;
  display: inline-block;
  font-size: clamp(1.3rem, 3vw, 1.75rem);   /* .stjarna sizes in em of this */
  line-height: 1;
  white-space: nowrap;
}

.hallen__stjarnor-tom,
.hallen__stjarnor-fylld {
  display: flex;
  /* No gap: the star's own viewBox carries it, so the row is exactly five equal
     boxes and the fill percentage is the plain fraction. See STJARNA. */
  gap: 0;
}

/* Konturen, så en tom stjärna syns som en plats och inte som ingenting. */
.hallen__stjarnor-tom { color: rgb(117 83 10 / 0.28); }

.hallen__stjarnor-fylld {
  position: absolute;
  inset: 0 auto 0 0;
  overflow: hidden;
  color: var(--guld-mork);
}

/* 28 units wide over 24 tall, gutter included. */
.hallen__stjarnor .stjarna { width: 1.1667em; height: 1em; flex: none; }

.hallen__punkt { margin: 0 0.4em; opacity: 0.5; }

/* Histogrammet: stjärnetikett, spår, exakt tal. Talkolumnen är fast bredd så de
   fem talen står på en gemensam högerkant i stället för att vandra med stapeln. */
/* Marginalen är NOLL nu: avståndet till snittet ägs av .hallen__jamn:s gap, och
   en egen margin-top ovanpå den hade lagt tillbaka en del av det som just togs
   bort -- i stapelläget som ett dubbelt gap, i radläget som en förskjutning nedåt
   av bara den ena kolumnen. Bredden i px i stället för max-width: auto-kolumnen i
   raden krymper annars till sitt innehåll och staplarna blir korta. */
.hallen__histogram {
  margin: 0;
  width: min(30rem, 100%);
  display: grid;
  gap: var(--s-2);
}

.hallen__stapelrad {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) 3.5rem;
  align-items: center;
  gap: var(--s-3);
}

.hallen__stapelnamn {
  display: flex;
  align-items: center;
  gap: 0.2em;
  font-family: var(--f-display);
  font-size: var(--t-sm);
  color: var(--guld-mork);
}

.hallen__stapelnamn .stjarna { width: 0.99em; height: 0.85em; }

.hallen__spar {
  display: block;
  height: 0.6rem;
  background: rgb(43 26 14 / 0.10);
}

/* min-width GÖR ETT OMDÖME SOM FINNS RITAT, oavsett hur smal skärmen är. Blocket
   påstår att varje omdöme visas, och sedan rubriken som sa det togs bort är
   stapeln hela beviset. Ettorna är 57 av 2 477, alltså 2,3 % -- vid 320 px mätte
   den stapeln 3,8 px, och varje smalare spalt tar den mot noll. Ett omdöme som
   finns får inte ritas som ingenting.
   Priset är att den smalaste stapeln kan ligga en tiondels px över sin andel på
   de smalaste vyerna. Det är billigare än att fördelningen tappar sin sista rad,
   och grindens proportionskontroll har 2 px att röra sig i. */
.hallen__stapel {
  display: block;
  height: 100%;
  min-width: 0.25rem;
  background: var(--guld-mork);
}

/* Rörelsen ligger bara på sidor med JS, för det är skriptet som parkerar
   staplarna på noll. Utan det står de på sin slutbredd och ska inte glida.
   Rörelsen själv är avstängd under prefers-reduced-motion av basregeln i
   styles.css, som klämmer varje transition till 0,001 ms -- skriptet returnerar
   dessutom före första ändringen, så ingenting hoppar. */
html[data-js="true"] .hallen__stapel,
html[data-js="true"] .hallen__stjarnor-fylld {
  transition: width 900ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Talen byter bredd medan de räknas upp, och en högerställd kolumn som växer
   flyttar sig i sidled hela vägen. Tabellsiffror håller varje glyf lika bred, så
   kolumnen står still. */
.hallen__tal,
.hallen__stapeltal,
.hallen__tal-text { font-variant-numeric: tabular-nums; }

.hallen__stapeltal {
  font-family: var(--f-bok);
  font-size: var(--t-sm);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Källa och datum. Liten, men inte gömd: den svarar på vilken dag talen gäller. */
.hallen__avlast {
  margin: var(--s-5) 0 0;
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--tra);
}

/* Guld i displaystorlek, det enda läge guld får vara text i på den här sajten.
   MEN MÖRKT GULD, inte ljust: --guld-ljus #e8c86a mäter 1,28:1 på blockets mark
   #ebe3d3 och är knappt en nyans (det var 1,11:1 på tidningspappret före
   2026-08-18 -- bytet av mark ändrade ingenting i sak). --guld-mork är samma familj
   och läsbart, 5,49:1. */
.hallen__tal {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 300;
  line-height: 1;
  font-size: clamp(3.2rem, 11vw, 6.5rem);
  letter-spacing: -0.01em;
  color: var(--guld-mork);
}
.hallen__tal-text {
  /* Sat under a centred figure with auto margins until 2026-08-12; it is now the
     right-hand column of .hallen__snitt and centring it there pulled it away
     from the stars it belongs to. */
  margin: 0;
  max-width: 30rem;
  font-family: var(--f-bok);
  font-size: var(--t-md);
  line-height: 1.5;
}

/* --- avslutet ---------------------------------------------------------- */

/* s-8 → s-6 och knappraden s-6 → s-5, 2026-08-17. Avslutet är två saker som hör
   ihop (en inbjudan och knappen den leder till), och de stod 64 px under talen
   med 32 px mellan sig -- alltså längre från varandra än de behövde och närmare
   Googles statistik än de såg ut att vara. */
.hallen__slut { margin-top: var(--s-6); text-align: center; }
.hallen__fraga {
  margin: 0 auto;
  max-width: 34rem;
  font-family: var(--f-bok);
  font-style: italic;
  font-size: var(--t-lg);
  line-height: 1.4;
}
.hallen__slut .knapp-rad { margin-top: var(--s-5); justify-content: center; }

/* ETTSTJÄRNI-GA. At 375 the heading broke mid-word, which reads as a typo rather
   than as a line break, and the cause is a PAIR rather than either half: .display
   sets text-wrap: balance and hyphens: auto, so Chrome optimises for equal line
   lengths and a hyphen inside the word is the evenest split it can find. Measured:
   170 px against 176 in a 327 px box. Both words fit their own line comfortably,
   so the hyphen buys nothing but the balance the browser was asked for.

   hyphens: manual, the same answer .pv2__rubrik and .ig__ord h2 already carry --
   the third heading on this site to hit it. The net is worth keeping on .display
   in general, because a 381 px word like INTEGRITETSPOLICY must not push the
   document sideways; it is only wrong where every word already fits.
   Swept after: 0 px of horizontal overflow from 320 to 1920. */
.hallen__ord h2 { hyphens: manual; }

/* start, not the grid default stretch: the long review set the row height and
   the short one rendered a gilt museum frame that was 55% bare walnut. Pinned
   clippings are never the same height anyway. */
.hallen__rutnat {
  align-items: start;
  display: grid;
  gap: var(--s-6);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 48rem) {
  /* start, not the grid default stretch: the long review set the row height and
   the short one rendered a gilt museum frame that was 55% bare walnut. Pinned
   clippings are never the same height anyway. */
.hallen__rutnat {
  align-items: start; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The bad reviews get the museum treatment. That is the joke. */
.recension {
  padding: var(--s-6);
  background: var(--valnot);
  color: var(--papper);
}

.recension blockquote {
  margin: 0 0 var(--s-4);
  font-style: italic;
  font-size: var(--t-md);
  line-height: 1.5;
}

.recension figcaption {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--guld-ljus);
}

.stjarnor {
  display: flex;
  gap: 0.15em;
  margin: 0 0 var(--s-4);
  font-size: var(--t-md);
  line-height: 1;
  letter-spacing: 0.1em;
}

.stjarnor--ett { color: var(--rod-ljus); }
.stjarnor--fem { color: var(--guld); }

/* The taped-up good reviews are on cream, so the gold steps down. */
.recension--bra .stjarnor--fem { color: var(--guld-mork); }

/* The good ones are taped up like the guest notices they actually print. */
.recension--bra {
  background: var(--papper-djup);
  color: var(--valnot);
  transform: rotate(-0.5deg);
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.28);
}

.recension--bra figcaption { color: var(--tra); }

.svaret {
  margin-top: var(--s-7);
  text-align: center;
}

.svaret__citat {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: var(--t-2xl);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--guld);
  margin: 0 0 var(--s-3);
}

.svaret__vem {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-vid);
  color: var(--papper);
  opacity: 0.75;
  margin: 0;
}

/* 4. Galleries and Instagram ============================================ */

.galleri {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 48rem) {
  .galleri { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.galleri img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}

.galleri--bred img { aspect-ratio: 4 / 3; }

.instagram__topp {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  margin-bottom: var(--s-5);
}

/* 5. Hitta hit ========================================================== */

.hitta__rutnat {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: minmax(0, 1fr);
}

/* .hitta__media STOD HÄR till 2026-08-18: ett eget rutnät som delade
   kontaktsidans spalt mellan ett fotografi och kartan i proportionen 1,1:1. Fotot
   är borta -- uteserveringen visas i heron i stället, och samma uteservering två
   gånger på en sida är en upprepning -- så kartan ÄR spalten nu och behöver ingen
   delning. Reglerna är raderade i stället för lämnade: en regel utan element är en
   fälla nästa gång någon söker efter var kartans höjd bestäms. git har dem.

   An iframe has no intrinsic height, so the frame has to state one. Stacked on
   a phone the map keeps a proportion of its own; from two columns up the
   proportion is dropped and the row height decides (see below).

   1:1 OCH INTE 4:3 PÅ TELEFON, samma dag och av samma skäl: fotot ovanför kartan
   bar en tredjedel av den staplade spalten, och när det försvann blev kartan den
   enda bilden i den. 245 px hög blev 327 -- fortfarande under en tredjedel av en
   667-skärm, alltså ingen vägg. */
.karta {
  position: relative;
  aspect-ratio: 1;
  margin: 0;
}

.karta__ram {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

@media (min-width: 52rem) {
  .hitta__rutnat { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* The photograph carries the column, so it is as tall as the facts beside it.
     A landscape frame left to its own height stopped a third of the way down and
     the paper below it read as a gap. Cropping is centred; the source is the
     corner of the building and survives losing its outer edges. Only from two
     columns up -- stacked on a phone the picture keeps its own proportions.
     Opt-in per page: the same grid carries the home page, whose picture has not
     been asked to crop. */
  .hitta__rutnat--jamnhog > figure,
  .hitta__rutnat--jamnhog > figure > .fotohorn { height: 100%; }
  .hitta__rutnat--jamnhog > figure img { width: 100%; height: 100%; object-fit: cover; }

  /* Same bargain one level down, but the row has to be told who decides. Left
     alone, the PHOTOGRAPH decides: a grid item contributes its content height
     to an auto row, so the picture set the row to 635px while the facts beside
     it wanted 441, and the balance had to be made up in bare paper or in gaps
     wide enough that the list stopped reading as a list.

     Taking the picture out of the intrinsic calculation (absolute, inset 0) is
     what hands the decision back: it now contributes nothing, so the row is as
     tall as the facts -- with a floor, because below roughly 30rem the map
     stops being a map and turns into a strip of water. One number, and it is
     the map's, not the photograph's.

     :has() keeps this to the contact page. Oktoberfest carries the same grid
     with a bare figure and has not asked for a floor. */
  /* 34rem och inte 30: golvet var satt för en spalt där kartan bara var den nedre
     halvan, och det är den inte längre. Uppmätt vid 1440x900 ger 34rem en karta på
     544 px mot 221 -- två och en halv gånger så stor, vilket är vad Dennis bad om.
     Uppgiftslistan bredvid mäter 441 px, alltså är det fortfarande KARTAN som sätter
     radens höjd och inte tvärtom; sjunker listan under golvet växer den inte.

     :has() håller det till kontaktsidan. Sällskapssidan bär samma rutnät med ett
     vanligt fotografi och har inte bett om något golv. */
  .hitta__rutnat--jamnhog:has(> .karta) { grid-auto-rows: minmax(34rem, auto); }

  /* Proportionen släpps i tvåspaltsformen: raden bestämmer höjden, och kartan
     fyller den genom .hitta__rutnat--jamnhog > figure { height: 100% } ovan. */
  .hitta__rutnat--jamnhog > .karta { aspect-ratio: auto; }

  /* And the other side of the balance: the facts spread into the height the
     media column asks for, instead of stopping short and leaving bare paper
     under them. space-between distributes the surplus into the gaps BETWEEN
     rows, so every line keeps its own height and only the breathing room
     grows -- unlike align-content: center, which hands each child exactly the
     height it asked for and pushes the surplus to the ends.

     When the text is the taller side there is no surplus and this does
     nothing, which is the right way for it to fail. */
  .hitta__rutnat--jamnhog > .hitta__text {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
  }
  .hitta__rutnat--jamnhog > .hitta__text .fakta { align-content: space-between; }
}

.fakta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-3) var(--s-5);
  margin: 0;
}

/* Child selectors: the opening hours are a nested list inside one dd, and its
   days are not labels of the fact list. */
.fakta > dt {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--tra);
  padding-top: 0.28em;
}

.band--valnot .fakta > dt { color: var(--guld); }

.fakta > dd { margin: 0; }

/* Opening hours: day left, time right, one row each, so the times line up on a
   single edge instead of ending sentences at different places. Same shape as
   the footer's hours, which a guest may have read a moment earlier. */
.tider {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s-1) var(--s-4);
  margin: 0;
  max-width: 22rem;
}

.tider dt { margin: 0; }
.tider dd { margin: 0; text-align: right; white-space: nowrap; }

/* Not opening hours, and not formatted as one: closed days are a sentence and
   the fair-weather line is a footnote to the whole table. */
.tider__stangt { margin: var(--s-2) 0 0; }

.tider__not {
  margin: var(--s-1) 0 0;
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  /* No opacity on top of --tra: at 0.8 this line measured 4.13:1 against the
     paper and the gate caught it. Full strength is 6.56:1. */
  color: var(--tra);
}

/* Kept as a visible placeholder block even when empty, on purpose: their
   holiday hours change and the heading has to be findable. */
.avvikande {
  margin-top: var(--s-5);
  padding-top: var(--s-4);
  border-top: 1px solid rgb(122 74 34 / 0.28);
}

.band--valnot .avvikande { border-top-color: rgb(245 239 228 / 0.22); }

/* A link on the walnut band takes the gilt, exactly as the footer's links do
   (.fot a in styles.css). The site's default link colour is --guld-mork, which
   is measured for cream -- on walnut it is 2.39:1, and qa.mjs was right to fail
   it the moment the first such link existed, which was the telephone number in
   the Större sällskap hero on 2026-08-14.

   :not(.knapp) because the buttons on these bands are anchors too, and they
   carry their own white on red. A rule with one more component than .knapp has
   would have quietly repainted every button on every dark band. */
.band--valnot a:not(.knapp) { color: var(--guld-ljus); }
.band--valnot a:not(.knapp):hover { color: var(--papper); }

/* 5b. Enquiry form, larger parties ======================================= */

/* TVÅ SPALTER: ORDEN OCH KORTET. Tre heroer bär det här rutnätet -- Oktoberfest
   (2026-08-17), sällskapssidan (samma dag) och kontakt (2026-08-18) -- och det stod
   som tre likadana regler i två filer, med en notis i vardera som lovade att talen
   var desamma. Ett löfte i en kommentar är inte en delad regel: den tredje sidan var
   tillfället att göra det till en. Klassen heter efter vad den gör och inte efter en
   sida, så nästa hero kan använda den utan att heta Oktoberfest.

   30rem är spaltens tak och inte kortets bredd -- kortet är smalare och centreras i
   spalten. Talet får inte sänkas utan att fallbacken under prefers-reduced-motion
   provas: den lägger korten i ett auto-fit-rutnät med 11rem-golv, och under 23rem
   faller spalten till EN kolumn med 368 px breda kort. Se notisen i matkarusell.css.

   En kolumn under brytpunkten, och orden ligger först i källan så ordningen är
   densamma i båda lägena. */
.hero-rutnat {
  display: grid;
  gap: var(--s-7);
  align-items: center;
}
@media (min-width: 58rem) {
  .hero-rutnat { grid-template-columns: minmax(0, 1fr) minmax(0, 30rem); }
}
/* KNAPPEN DIREKT EFTER TEXTEN PÅ TELEFON, sällskapssidan. Låg efter bilderna
   2026-08-19 ("byta plats så bildspelet och boka sällskap knappen"), Dennis
   2026-08-20 flyttade upp den igen -- tillbaka till källordningen
   (ord/cta/bunt), som en egen rutnätscell håller oavsett var i markupen den
   står. Samma knep som .matkar__cta i matkarusell.css, och :has() håller det
   till sällskapssidan -- Oktoberfest saknar knappen i heron och Kontakts kort
   har ingen cta, så bara den grid som faktiskt har .storre-hero__cta rör sig. */
.hero-rutnat:has(.storre-hero__cta) { grid-template-areas: "ord" "cta" "bunt"; }
.hero-rutnat:has(.storre-hero__cta) .storre-hero__ord { grid-area: ord; }
.hero-rutnat:has(.storre-hero__cta) .matkar--fri { grid-area: bunt; }
/* .knapp-rad är en <p> och bär stilmallens paragraf-margin-top (~17px) -- ren
   luft ovanpå rutnätets eget gap, i BÅDA formerna (mobilens "cta" sist i en
   stack, desktopens egen rad). Samma nollning som .bok-portal och
   .okc-datum__knapp redan gör på samma klass av samma skäl. */
.hero-rutnat:has(.storre-hero__cta) .storre-hero__cta { grid-area: cta; margin-top: 0; }
@media (min-width: 58rem) {
  .hero-rutnat:has(.storre-hero__cta) {
    grid-template-areas: "ord bunt" "cta bunt";
  }
  /* Knappen kändes lös mot texten, Dennis 2026-08-20. Båda cellerna centrerades
     var för sig i sin rad (hero-rutnats align-items:center), och "bunt"
     (bildstapeln) spänner över båda raderna och är mycket högre än text+knapp
     tillsammans -- den extra höjden lades som luft ovanför och under var cell.
     Text mot sin rads underkant, knapp mot nästa rads överkant: bara gap
     (--s-7) kvar mellan dem. Bilden är orörd, den centreras fortfarande över
     hela spannet. */
  .hero-rutnat:has(.storre-hero__cta) .storre-hero__ord { align-self: end; }
  .hero-rutnat:has(.storre-hero__cta) .storre-hero__cta { align-self: start; }
}
/* UTAN SCROLL PÅ EN VANLIG TELEFON, Dennis 2026-08-19: hero-text plus polaroid ska
   rymmas på en gång vid 390x844 (iPhone 14/15-storlek). Uppmätt: sidhuvud 70 +
   hero 804 = 874, 30 px för mycket. --s-7 (48px) var talet EN kolumn ärvde av
   TVÅ-kolumnläget, där det bara är luft mellan text och bild -- staplat på en
   telefon är det också allt utrymme mellan styckets sista rad och fotot, och där
   finns inget att visa i det tomrummet. */
@media (max-width: 57.999rem) {
  .hero-rutnat { gap: var(--s-1); }
  /* Sällskapssidans tre staplade delar (text/knapp/bilder) läste som en enda
     klump vid 4px, Dennis 2026-08-20: "ge lite spacing ... men man ska
     fortfarande kunna se allt utan att scrolla". :has() håller det till just
     den här heron -- Oktoberfest och Kontakt har bara två delar och rör sig
     inte. --s-3 (12px) valt för att content fortfarande landar under
     --sidhero-tak (640 px) vid 390x844, alltså ingen extra scroll där. */
  .hero-rutnat:has(.storre-hero__cta) { gap: var(--s-3); }
}
/* Bandet är valnöt och .brod ärver inte dess färg av sig själv -- samma rad som
   okc-hero__ord bär, av samma skäl. */
.storre-hero__ord .brod { color: inherit; }

/* Fields drawn as ruled lines on paper rather than as boxes: this is a page
   from their book, and a stack of grey rounded rectangles from a settings
   dialog would be the one thing on the site that came out of a template. The
   rule under each field is the same walnut as the text.

   WHAT MADE IT FINDABLE, Dennis 2026-08-14 ("gör formuläret lite mer synlig"):
   not louder fields, but a CARD. The rules were drawn on the same paper as the
   band they sat on -- #ebe3d3 under #ebe3d3 -- so a hairline at 45 % walnut was
   the only thing saying "form", and at a glance the section read as another
   paragraph. The card is the site's two papers doing the work they already do
   in the book: the lighter cream lifted off the deeper one, hairline edge, one
   soft shadow. The fields then get the DEEPER paper as their ground, so each
   one is a well cut into the card rather than a line floating on it -- and the
   rule can stay a rule.

   Both papers are the site's own tokens, so the form cannot drift away from the
   page it is printed on. */

/* The card is the target of the hero's button, so it carries tabindex="-1" --
   without it the jump moves the view and leaves focus at the top of the page,
   and the next Tab starts the journey again. A card is not a control, so it
   gets no ring for a mouse; a keyboard arrival still gets one, which is the
   only signal that says "you are here now". */
.forfragan:focus { outline: none; }
.forfragan:focus-visible {
  outline: 2px solid var(--guld-mork);
  outline-offset: 4px;
}

.forfragan {
  background: var(--papper);
  border: 1px solid rgb(122 74 34 / 0.28);
  padding: clamp(1.5rem, 4.5vw, 2.75rem);
  box-shadow: 0 1.25rem 2.5rem rgb(43 26 14 / 0.10);
}

.formular {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-5);
  margin-top: var(--s-6);
}

@media (min-width: 40rem) {
  .formular { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .falt--bred,
  .formular__knappar { grid-column: 1 / -1; }
}

.falt {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin: 0;
}

.falt label {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--tra);
}

/* The star that says a field is needed, and it is deliberately NOT inside the
   element that carries data-sv: sprak.js swaps textContent wholesale, so a
   child of a translated element is wiped the first time the language changes.
   It is a sibling inside the label instead.

   aria-hidden, because the input's own required attribute already tells a
   screen reader the same thing, and hearing "star" before every field name is
   noise. The red is the deep one -- the ordinary red is a button colour and
   would read as something to press. */
.falt__krav {
  margin-left: 0.2em;
  color: var(--rod-djup);
  font-weight: 700;
}

.formular__krav {
  margin: var(--s-3) 0 0;
  font-family: var(--f-bok);
  font-size: var(--t-sm);
  color: var(--tra);
}

.falt input,
.falt textarea {
  /* PLATTFORMEN FÅR INTE ÄGA FORMEN PÅ ETT FÄLT, och det är datum- och
     tidsfälten som gör raden nödvändig: de är native kontroller, så utan detta
     ritar iOS sin egen rundade ruta med sin egen höjd och sitt eget innehåll --
     alltså står exakt de två fälten ut ur ett formulär där allt annat är
     rätvinkligt. Dennis 2026-08-17: det har hänt i varje formulär vi byggt.
     `appearance: none` är det ENDA som tar formen från plattformen; en
     `border-radius: 0` bredvid är utan verkan så länge kontrollen är native
     (Chrome rapporterar till och med tillbaka 0px medan widgeten är rund). */
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  color: var(--valnot);
  /* The deeper paper as the field's own ground: a well cut into the card,
     which is what makes a field read as a field before anyone has clicked it.
     Transparent was invisible against a card of the same cream. */
  background: var(--papper-djup);
  border: 0;
  border-bottom: 2px solid rgb(122 74 34 / 0.55);
  border-radius: 0;               /* iOS rounds text inputs on its own */
  padding: var(--s-2) var(--s-3);
  /* 44px of tappable height, the same floor as the buttons. */
  min-height: 2.75rem;
  width: 100%;
}

/* SISTA TVÅ PIXLARNA AV SAMMA FEL. `appearance: none` ovan tar formen från
   plattformen men inte höjden: datum- och tidsfälten mätte 47 px mot de andra
   fältens 45, alltså stack de fortfarande ut ur raden. Höjden kommer inte från
   pickerikonen utan från fälten-omslaget inuti kontrollen, som webbläsaren ger
   1 px padding över och under. Mätt fram genom att prova sju kandidater i tur
   och ordning -- det här är den enda som flyttade talet.

   Skriv ALDRIG en fast höjd här i stället. Fältet skulle sluta följa
   teckenstorleken, och felet kommer tillbaka tyst första gången någon ändrar
   typografin. Grinden i tools/qa.mjs mäter numera att alla fält i ett formulär
   är lika höga. */
.falt input::-webkit-datetime-edit-fields-wrapper {
  padding: 0;
}

.falt textarea {
  border: 1px solid rgb(122 74 34 / 0.35);
  border-bottom-width: 2px;
  border-bottom-color: rgb(122 74 34 / 0.55);
  padding: var(--s-3);
  resize: vertical;
}

.falt input:focus-visible,
.falt textarea:focus-visible {
  outline: 2px solid var(--guld-mork);
  outline-offset: 2px;
}

/* :invalid alone paints every required field red before a word is typed. The
   browser sets :user-invalid only after the visitor has actually left the field
   or tried to submit, which is when a warning is information rather than an
   accusation. */
.falt input:user-invalid,
.falt textarea:user-invalid { border-color: var(--rod-djup); }

.formular__knappar { margin: 0; }

/* TACKVYN, Dennis 2026-08-19: formuläret förvandlas till ett tackblock när det
   är ifyllt och skickat. Samma kort, samma papper och samma kant -- det är bara
   orden i kortet som byts, och därför står ingen ny ram, ingen ny färg och inget
   nytt band här. Vad kortet visar när, och varför båda vyerna finns i markup,
   står i tools/sida_ovriga.py.

   :not([hidden]) OCH INTE BARA .forfragan__tack, för display i en regel utan det
   skulle slå hidden och vyn stod framme från början. Skriptet växlar attributet;
   den här raden gör att attributet betyder något. */
/* CENTRERAT, Dennis 2026-08-19: rubriken och raden under den står i mitten.
   justify-items styr grid-barnens läge -- alltså också guldstrecket, som är ett
   av dem och därför centreras med rubriken utan en egen regel. text-align på
   rubriken och styckena gör resten: en centrerad låda med vänsterställd text är
   det vanligaste sättet att missa halva greppet.

   KVITTOT ÄR MED FLIT UNDANTAGET. Det är en lista med etikett till vänster och
   värde till höger, och den formen kommer ur att raderna kan läsas i en kolumn --
   centrerade skulle de bli tre par som flyter. Se .tackkvitto__rad. */
.forfragan__tack:not([hidden]) {
  display: grid;
  gap: var(--s-4);
  justify-items: center;
  text-align: center;
}

.forfragan__tack .tackkvitto { text-align: left; }

/* RADLÄNGDEN ÄR DEL AV CENTRERINGEN. Stycket löpte över kortets fulla 660 px och
   bröt 90/18 tecken -- en lång rad med ett kort svansstycke under, vilket är det
   som får centrerad text att se oavsiktlig ut. 34rem ger två rader av jämn längd
   utan att ett tal per språk behövs: engelskan är längre och bryter till tre. */
.forfragan__tack .brod {
  max-width: 34rem;
  /* Och `balance` ovanpå bredden, för bredden ALLENA kan inte ge två jämna rader
     i två språk: 34rem bröt svenskan 87/21 tecken. Detta låter webbläsaren jämna
     ut raderna själv (den gör det bara upp till några få rader, vilket är exakt
     vad ett stycke som det här är). Där det inte stöds står 34rem kvar och
     stycket ser ut som det gjorde -- ingen layout hänger på egenskapen. */
  text-wrap: balance;
}

/* Guldstrecket är samma sorts tryckta markering som resten av sajten sätter över
   en rubrik, ritat och inte importerat: ett grid-barn på 3rem. Det bär ingen
   information, alltså finns det inget att läsa upp och ::before är rätt plats.

   STRECKET OCH ÖGONBRYNET SITTER IHOP sedan "Danke schön" kom in 2026-08-19:
   ögonbrynets egen bottenmarginal (--s-3) plus vyns gap (--s-4) hade lagt 52 px
   mellan frasen och rubriken den hör till, alltså läst som två ensamma rader.
   Strecket, frasen och rubriken är EN tryckt enhet -- gapet mellan dem nollas och
   luften ligger runt gruppen i stället. */
.forfragan__tack:not([hidden])::before {
  content: "";
  width: 3rem;
  height: 2px;
  background: var(--guld-mork);
  margin-bottom: calc(var(--s-4) * -1 + var(--s-2));
}

/* HANDEN, Dennis 2026-08-19: samma skrivstil som repliken vid portionsreglaget på
   menysidan (.hunger__replik) -- husets röst, inte husets etikett. Caveat alltså,
   och därmed ingen text-transform och ingen spärrning: versaler och letter-spacing
   är vad ett ögonbryn behöver och vad en handskrift går sönder av.

   GULDET ÄR DET MÖRKA och inte replikens ljusa. Repliken står på valnöt; det här
   står på kräm, där --guld mäter 2,1:1 och är oläsligt. Regeln står i styles.css
   överst: aldrig --guld på --papper. Samma fras, samma hand, annan grund.

   Storleken är replikens nedre ände. Handen ska vara en röst före rubriken, inte
   en andra rubrik -- över 1,5rem börjar den konkurrera med bok-rubriken under. */
.forfragan__danke {
  display: block;
  font-family: var(--f-hand);
  font-size: clamp(1.25rem, 1rem + 0.8vw, 1.5rem);
  line-height: 1.15;
  color: var(--guld-mork);
  margin-bottom: calc(var(--s-4) * -1);
}

/* Fokusmålet är vyn, inte en kontroll i den (se storre.js), och en yta som får
   fokus ska inte bära musens ring. Ett tangentbord som landade här får den. */
.forfragan__tack:focus { outline: none; }
.forfragan__tack:focus-visible {
  outline: 2px solid var(--guld-mork);
  outline-offset: 4px;
}

/* Kvittot ligger på det DJUPARE pappret, alltså exakt den grund fälten stod på i
   vyn innan -- uppgifterna är kvar där de skrevs in, och kortet över dem är
   fortfarande den ljusare krämen. Samma par papper som boken använder. */
.tackkvitto {
  margin: 0;
  width: 100%;
  display: grid;
  gap: var(--s-3);
  background: var(--papper-djup);
  border: 1px solid rgb(122 74 34 / 0.28);
  padding: clamp(1rem, 3vw, 1.5rem);
}

/* Etikett och värde på samma rad så länge de ryms, och radbrytningen är en
   WRAP och inte en krympning: ett flex-barn krymper tyst till en spalt på tre
   tecken innan det bryter, och en e-postadress är det längsta som kan stå här. */
.tackkvitto__rad {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2) var(--s-4);
}

.tackkvitto dt {
  flex: 0 0 auto;
  font-family: var(--f-display);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--tra);
}

.tackkvitto dd {
  margin: 0;
  font-family: var(--f-bok);
  color: var(--valnot);
  overflow-wrap: anywhere;        /* an address is one long word */
}

/* Växlingen får tona in, men bara där rörelse är välkommen: den som slagit av
   rörelse ska få vyn stående, inte en långsammare version av samma sak. */
@media (prefers-reduced-motion: no-preference) {
  html[data-js="true"] .forfragan__tack:not([hidden]) {
    animation: tackvy-in 260ms ease-out both;
  }
}

@keyframes tackvy-in {
  from { opacity: 0; transform: translateY(0.5rem); }
  to   { opacity: 1; transform: none; }
}

/* 6. Menu page ========================================================== */

/* Sticks directly under the header. The offset cannot be a constant: the header
   is content-driven and measured 127px at 1440 and 92px at 375, while this used
   to sit at a hard 4.25rem and hid behind it. menynav.js keeps --topp-h in sync;
   the fallback in var() is only for the moment before the script runs. */
.menynav {
  /* 12 luminance values against the page and one hairline is not enough
     separation: menu text was sliced mid-glyph at the bar's edge and read as a
     clipping fault. */
  box-shadow: 0 6px 14px rgb(43 26 14 / 0.10);
  position: sticky;
  top: var(--topp-h, 4.25rem);
  z-index: 30;
  /* Same paper as the header above and the page below, so the bar reads as part
     of the sheet rather than a grey band laid across it. The colour step used to
     do half the work of separating the bar from what scrolls under it; with the
     step gone the shadow below does all of it, which is why it stays. */
  background: var(--papper);
  border-bottom: 1px solid rgb(122 74 34 / 0.28);
}

/* A wrapper the two rows can be laid out against when a design wants them on
   one line. display:contents means it costs nothing until something asks for
   it: the rows lay out against .menynav exactly as if it were not there. */
.menynav__inre { display: contents; }

/* The two halves of the menu, as the first row of the same sticky bar. Keeping
   them inside .menynav rather than above it means one sticky element instead of
   two: --menynav-h already measures this bar, so scroll-padding-top stays
   correct without a third offset being added to the two that already sum. */
.menynav__flikar {
  display: flex;
  justify-content: center;
  gap: var(--s-4);
  border-bottom: 1px solid rgb(122 74 34 / 0.16);
}

.menyflik {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 3px solid transparent;
  min-width: 6rem;
  min-height: 3.5rem;
  padding: var(--s-4) var(--s-5);
  font-family: var(--f-display);
  /* Two rows of the same uppercase display face read as one indecisive bar if
     they are near the same size. 17px over 12px is what makes the first row the
     question and the second the answer. */
  font-size: var(--t-base);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--valnot);
  cursor: pointer;
}

.menyflik[aria-selected="true"] {
  border-bottom-color: var(--rod);
  color: var(--rod);
}

/* The chips of the closed half. [hidden] is display:none in the UA sheet, but
   this bar is a flex container and one stray display rule would undo it
   silently -- so it is said here too, where it cannot be lost. */
.menynav__spar li[hidden] { display: none; }

/* Centred while the chips fit, scrolling from the left once they do not.
   `fit-content` plus a max-width does that without `justify-content: center`,
   which in a scroll container pushes the first chip off the left edge where no
   amount of scrolling can reach it. At 375px the track measures 492 against 327
   of room, so that case is real and not hypothetical. */
.menynav__spar {
  display: flex;
  gap: var(--s-5);
  overflow-x: auto;
  overflow-y: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
  width: fit-content;
  max-width: min(100% - 2 * var(--s-5), var(--matt));
  margin-inline: auto;
  scrollbar-width: none;
  white-space: nowrap;
  scroll-behavior: smooth;
}

.menynav__spar::-webkit-scrollbar { display: none; }

.menynav a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  min-height: 3.25rem;
  padding: var(--s-4) var(--s-2);
  font-family: var(--f-display);
  font-size: var(--t-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--valnot);
  text-decoration: none;
  border-bottom: 3px solid transparent;
}

/* Thinner than the tab's 3px: the same mark at two weights says which level is
   speaking without needing a second colour. */
.menynav a { border-bottom-width: 2px; }

.menynav a[aria-current="true"] {
  border-bottom-color: var(--rod);
  color: var(--rod);
}

/* Their printed menu is centred geometric capitals with the price on the
   heading line and the description beneath. We keep that voice exactly. */
/* Luften i menyn stramades åt, Dennis 2026-08-14: "lite mycket spacing mellan
   menyerna". Uppmätt före mellan sista rätten i en kategori och nästa
   kategorirubrik: 183 px på 1440, 188 på 375. Tre led låg i den siffran och
   bara ett av dem syntes i en enskild regel -- gruppens padding nedåt, bandets
   padding nedåt och nästa bands padding uppåt summerade. Nu 131 px. Bandet
   skruvas bara INNE i menypanelerna: .band är sajtens allmänna mark och bär
   startsidan, historien och oktoberfest med samma tal.

   ANDRA VARVET, samma dag: Dennis pekade på Tillbehör -> Dessert och ville ha
   det kortare. Måttet var 130 px ovanför rubriken och 33 px under den, ner till
   första rätten -- fyra gånger så mycket luft över en rubrik som under den, så
   den svävade utan att tillhöra något. Både bandet och gruppen gick ned ett steg
   i skalan. GRUPPEN måste följa med: bandets padding är det enda som skiljer en
   KATEGORI från nästa, medan två grupper inne i en kategori skiljs av två
   gruppaddingar. Skruvas bara bandet blir kategoribrytet mindre än gruppbrytet,
   alltså hierarkin baklänges -- den lilla avdelaren får mer luft än den stora. */
.mengrupp { padding-block: var(--s-5); }
.mengrupp + .mengrupp { border-top: 1px solid rgb(122 74 34 / 0.2); }

.menypaneler .band { padding-block: var(--s-6); }

.mengrupp__rubrik {
  font-family: var(--f-display);
  font-size: var(--t-lg);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--spar-vid);
  text-align: center;
  margin: 0 0 var(--s-2);
}

.mengrupp__under {
  font-family: var(--f-display);
  font-size: var(--t-sm);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  text-align: center;
  color: var(--tra);
  margin: 0 0 var(--s-6);
}

.menypost {
  text-align: center;
  max-width: 44rem;
  margin-inline: auto;
  padding-block: var(--s-3);
}

.menypost__namn {
  font-family: var(--f-display);
  font-size: var(--t-md);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0;
}

.menypost__pris { white-space: nowrap; }

.menypost__enhet {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: var(--spar-display);
  text-transform: uppercase;
  color: var(--tra);
}

.menypost__desc {
  font-style: italic;
  margin: var(--s-1) 0 0;
  /* Centreringen deklareras HÄR, inte bara på .menypost. Beskrivningen ligger
     oftast inne i en post och ärvde den därifrån -- men tre stycken ligger
     direkt i gruppen utan post omkring sig (Vatten, Cocktails, och fotnoterna),
     och de stod vänsterställda mitt i en genomgående centrerad meny. Uppmätt
     2026-08-14 på 1440: 380 px snedhäng på vattentexten, 252 på cocktailtexten.
     Ärvd typografi håller bara så länge varje förekomst har samma förälder. */
  text-align: center;
}

/* De två beskrivningar som ligger direkt i gruppen (Vatten och Cocktails) har
   ingen .menypost omkring sig och fick därför hela bandets bredd -- 1184 px vid
   1440, alltså EN rad på 804 respektive 932 px. Centrerad eller ej läser en rad
   så bred inte som en mening utan som en rubrikrad. Dennis 2026-08-14: två
   rader. Satsbredden är sajtens egen --matt-text, inget nytt tal, och
   text-wrap: balance delar raderna jämnt i stället för att fylla den första och
   lämna en stump: uppmätt gick andra raden från 299 till 415 px på vattnet.
   Uppmätt 2 rader från 1440 ned till 600 px bredd; under det tar texten den
   plats den behöver, som all annan brödtext på en telefon. */
.mengrupp > .menypost__desc {
  max-width: var(--matt-text);
  margin-inline: auto;
  text-wrap: balance;
}

/* Fotnoten som STYCKE är en rad text under en centrerad lista och centreras.
   Fotnoterna som LISTA (Från köket) behåller sina punkter och sin vänsterkant
   -- en punktlista med centrerade rader har ingen kant att läsa längs. */
p.menynot { text-align: center; }

/* The spirits list is long and numbered by the client, so it stays a table:
   the number and the two pour sizes are data, not prose. */
.spritbord {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--f-display);
  font-size: var(--t-sm);
  letter-spacing: 0.03em;
}

.spritbord caption {
  font-family: var(--f-display);
  font-size: var(--t-lg);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--spar-vid);
  padding-bottom: var(--s-4);
}

.spritbord th,
.spritbord td {
  padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid rgb(122 74 34 / 0.18);
  text-align: left;
}

.spritbord th {
  font-weight: 500;
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  color: var(--tra);
}

.spritbord td:first-child { width: 3.5rem; color: var(--tra); }
.spritbord th:not(:first-child):not(:nth-child(2)),
.spritbord td:not(:first-child):not(:nth-child(2)) {
  text-align: right;
  width: 5rem;
  white-space: nowrap;
}

.menynot {
  max-width: var(--matt-text);
  margin: var(--s-6) auto 0;
  font-size: var(--t-sm);
  color: var(--valnot-mjuk);
}

.menynot li + li { margin-top: var(--s-2); }

/* 7. Historien ========================================================== */

.tidslinje {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s-7);
}

.epok {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 52rem) {
  .epok { grid-template-columns: 7rem minmax(0, 1fr); }
}

.epok__ar {
  font-family: var(--f-display);
  font-weight: 300;
  font-size: var(--t-xl);
  letter-spacing: 0.02em;
  color: var(--rod);
  margin: 0;
  line-height: 1;
}

.urklipp__kalla {
  font-family: var(--f-hand);
  font-size: var(--t-md);
  color: var(--valnot-mjuk);
  margin: var(--s-3) 0 0;
  transform: rotate(-1deg);
}

/* 8. Text pages ========================================================= */

.textsida h2 {
  font-family: var(--f-bok);
  font-weight: 600;
  font-size: var(--t-lg);
  color: var(--guld-mork);
  margin: var(--s-7) 0 var(--s-3);
}

.textsida h3 {
  font-family: var(--f-display);
  font-size: var(--t-sm);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--spar-display);
  margin: var(--s-5) 0 var(--s-2);
}

.textsida p,
.textsida li { max-width: var(--matt-text); }

.textsida ul { padding-left: var(--s-5); }
.textsida li + li { margin-top: var(--s-2); }

/* A caption. This class was used before it existed, which the contrast gate
   could not tell me — it only saw the colour it inherited. */
.bildtext {
  font-family: var(--f-display);
  font-size: var(--t-xs);
  letter-spacing: var(--spar-display);
  line-height: 1.5;
  margin-top: var(--s-3);
  color: var(--tra);
}

.band--valnot .bildtext { color: var(--guld-ljus); }

/* Historien: Kenar's tools, the clipping wall, the Kära gäst notice ======= */
/* All three arrived with the art director's material on 2026-07-29. */

.verktyg {
  display: grid;
  gap: var(--s-6);
  align-items: start;
}

@media (min-width: 52rem) {
  .verktyg { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
}

.verktyg__rad {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
  align-items: center;
  margin-top: var(--s-5);
}

.verktyg__rad img { width: 100%; height: auto; }

/* The clippings are photographs of paper, so they get paper to sit on rather
   than floating on the newsprint ground. */
.urklippsvagg {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* Each card is only as tall as its own clipping. Stretched rows gave the short
     ones a screen of empty paper underneath. */
  align-items: start;
  margin-top: var(--s-6);
}

@media (min-width: 52rem) {
  .urklippsvagg { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.urklipp {
  margin: 0;
  background: var(--papper);
  padding: var(--s-4);
  box-shadow: 0 1px 2px rgb(43 26 14 / 0.16), 0 10px 24px -14px rgb(43 26 14 / 0.4);
}

.urklipp:nth-child(odd) { rotate: -1.1deg; }
.urklipp:nth-child(even) { rotate: 0.9deg; }
.urklipp img { width: 100%; height: auto; }

.urklipp figcaption {
  margin-top: var(--s-3);
  text-align: center;
  color: var(--valnot);
}

.karagast {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: var(--s-6);
}

.karagast__rubrik {
  font-size: clamp(1.6rem, 1.1rem + 2.4vw, 2.6rem);
  color: var(--guld-mork);
  transform: none;
  margin: 0;
}

.karagast__ram { width: min(24rem, 100%); }


/* Menu opening: the gilt frame from the start page, put to work =========== */
/* Dennis liked the frame the one-star reviews hang in, so the menu borrows it.
   The page had no photograph at all before this. The frame's inner ground is
   walnut, which is also the band, so the gold edge is what separates them. */

/* stretch, not center: the frame is the block's other half and should stand
   as tall as it. Centred, it measured 512px against the text column's 700 and
   read as a picture dropped into the band rather than as one of two columns. */
.menytopp {
  display: grid;
  gap: var(--s-6);
  align-items: stretch;
}

@media (min-width: 52rem) {
  .menytopp { grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr); }
}

.menytopp__ram { width: 100%; margin: 0; }

/* The frame fills its cell, the mount fills the frame, and the photograph
   fills the mount -- three links in one chain, and the picture only reaches
   the bottom if every one of them holds. */
.menytopp__ram { display: grid; grid-template-rows: 1fr auto; }
.menytopp__ram .ram__inre { display: grid; grid-template-rows: 1fr auto; min-height: 0; }

.menytopp__ram figcaption {
  padding: var(--s-3) var(--s-4) var(--s-4);
  margin-top: 0;
  text-align: center;
}


/* The dishes, horizontally in the selector's own block ==================== */
/* They sat in a block of their own below, with a heading and a rule of their own,
   which made them a second section pretending not to be one. They now lie in the
   same column as the slider, in a row: paper with the picture inset, the caption
   handwritten underneath, one strip of tape.

   The column is 784px wide at 1440, so four frames share it at about 11rem each
   rather than the 15rem they had when they owned a whole band. */

.smakprov__rad {
  list-style: none;
  margin: clamp(var(--s-6), 3vw, var(--s-7)) 0 0;
  /* The staggered cards are pushed down by up to 1.2rem and the rotation adds a
     little more, so the row carries that as padding. Without it the lowest frame
     hung 23px past the row and into the button below it. */
  padding-bottom: var(--s-6);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(var(--s-5), 3vw, var(--s-6)) 0;
  justify-items: center;
}

/* 72rem, not 52rem. The row lives inside .hunger__rutnat's second column, and a
   nested grid cannot borrow its parent's breakpoint: its own is the parent's plus
   whatever the sibling columns eat. Four 11rem cards need 44rem, the photograph
   column takes 22rem and the gap 3rem, so 52 + 22 + 3 rounds to 72rem.
   At 52rem the cards collapsed from 176px to 96px across a single pixel of
   viewport and only recovered at 1180. */
/* In its own column the row becomes a loose 2 by 2 cluster: two per row at 9rem,
   each nudged and tilted differently so it reads as photographs put down rather
   than a grid. */
@media (min-width: 72rem) {
  .smakprov__rad {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-4) 0;
    margin-top: 0;
    padding-bottom: var(--s-5);
  }

  .smakprov__rad .polaroid { width: min(9rem, 100%); }

  /* The tape was sized for a 15rem card and covers half of a 9rem one. */
  .polaroid__tejp { width: 2.8rem; top: -0.5rem; }

  .polaroid:nth-child(1) { rotate: -4deg;   translate: 0.4rem 0; }
  .polaroid:nth-child(2) { rotate: 3deg;    translate: -0.6rem 1.4rem; }
  .polaroid:nth-child(3) { rotate: 2.4deg;  translate: 0.8rem -0.4rem; }
  .polaroid:nth-child(4) { rotate: -2.6deg; translate: -0.4rem 1rem; }
}

.polaroid {
  position: relative;
  background: var(--papper);
  padding: var(--s-2) var(--s-2) 0;
  width: min(11rem, 100%);
  max-width: 100%;
  /* Walnut, like every other tilted-paper shadow on the site. Two of them cast
     black and two cast walnut before this. */
  box-shadow:
    0 1px 2px rgb(43 26 14 / 0.34),
    0 14px 24px -14px rgb(43 26 14 / 0.7);
  transition: rotate 220ms ease, translate 220ms ease;
}

/* Rotations and heights per card, so the row is deliberate and identical on every
   build. Equal frames hung at equal heights read as a filmstrip however much they
   are tilted. */
.polaroid:nth-child(1) { rotate: -3deg;   translate: 0 0; }
.polaroid:nth-child(2) { rotate: 2.2deg;  translate: 0 0.9rem; }
.polaroid:nth-child(3) { rotate: -1.6deg; translate: 0 0.2rem; }
.polaroid:nth-child(4) { rotate: 2.8deg;  translate: 0 1.2rem; }

/* No negative inline margins here. Symmetric ones cancel under
   justify-items: center — the margin box centres and the border box lands in
   exactly the same place, verified identical at 900, 1024, 1180 and 1440. The
   overlap that does read comes from the rotation widening each bounding box, and
   document order already paints later cards on top, so the z-index ladder that
   used to sit here only restated the default. */

.polaroid:hover,
.polaroid:focus-within {
  rotate: 0deg;
  translate: 0 -0.4rem;
  z-index: 5;
}

.polaroid__bild {
  display: block;
  background: var(--valnot);
}

.polaroid__bild img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

/* The caption is written under the picture, on the paper, so it takes the paper's
   ink and not the band's. Measured at 13.8:1 for this pair. */
.polaroid__text {
  font-family: var(--f-hand);
  font-size: 0.95rem;
  line-height: 1.2;
  color: var(--valnot);
  padding: var(--s-2) 0 var(--s-3);
  margin: 0;
}

.polaroid__tejp {
  position: absolute;
  top: -0.7rem;
  left: 50%;
  translate: -50% 0;
  width: 4.2rem;
  height: auto;
  rotate: -3deg;
  z-index: 2;
  pointer-events: none;
}


/* Equal buttons on mobile ================================================= */
/* At 375px the CTAs measured 297, 150 and 196px wide. One column of equal widths
   reads as a set; three different widths reads as three unrelated controls.
   Desktop keeps them inline, where varying widths are normal. */
@media (max-width: 40rem) {
  .knapp-rad {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-3);
    justify-items: stretch;
  }

  .knapp-rad .knapp { width: 100%; }
}

/* The nudge over the slider. Nobody drags a control they have not noticed is
   draggable, and the four chips underneath make it look like the row is the
   whole interface. Gold on walnut with cream ink is the same pairing the
   active chip uses, so the hint reads as part of the control rather than as a
   notification the page has produced. */
.hunger__vink {
  display: inline-block;
  position: relative;
  margin-bottom: var(--s-4);
  padding: var(--s-2) var(--s-3);
  background: var(--guld);
  color: var(--valnot);                    /* 6.9:1 */
  font-family: var(--f-hand);
  font-size: 1.25rem;
  line-height: 1.15;
  transform-origin: 20% 100%;
  animation: fb-vink 2.8s ease-in-out infinite;
}

/* The tail, pointing down at the track it is talking about. */
.hunger__vink::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 1.4rem;
  border: 7px solid transparent;
  border-top-color: var(--guld);
  border-bottom: 0;
}

/* Rightwards, because that is the direction the sentence asks for. Transform
   only, so it never costs a layout. */
@keyframes fb-vink {
  0%, 62%, 100% { transform: translateX(0); }
  72%           { transform: translateX(6px); }
  82%           { transform: translateX(0); }
  92%           { transform: translateX(4px); }
}

/* Gone on first contact, and gone for the rest of the visit -- a hint that
   comes back after it has been obeyed is a nag. */
.hunger--rord .hunger__vink {
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 260ms ease, transform 260ms ease, visibility 0s 260ms;
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .hunger__vink { animation: none; }
  .hunger--rord .hunger__vink { transition: none; }
}


/* Menyheron ryms på en skärm ============================================== */
/* Dennis 2026-08-10: "gör så att man inte behöver scrolla i heron, gör så allt
   får plats". Uppmätt före, sidhuvud + hero mot skärmhöjden:

       1440x900   127 + 883    110 px över vikningen
       1440x700   127 + 883    310 px
       768x1024    93 + 1543   612 px
       390x844     92 + 1252   500 px
       375x667     92 + 1235   660 px

   Heron var byggd av sitt innehåll och råkade bli hög. Nu är HÖJDEN
   utgångspunkten och kompositionen krymper i den.

   KOMPOSITIONEN krymper -- behållaren kapar aldrig. En max-height med overflow
   raderar innehåll i stället för att visa mindre av det, och en hero som
   klipper sin egen prisrad är sämre än en som scrollar.

   Sidhuvudets höjd mäts redan i JS: meny-luckan.js skriver --topp-h med en
   ResizeObserver, eftersom språkväxlaren radbryter navigeringen utan att
   fönstret ändras. Ingen höjd hårdkodas här. Reservvärdet gäller bara första
   bildrutan innan observern hunnit skriva, och det är per bredd: 5,75rem är
   den hopfällda baren, 8rem den utfällda. */

/* SIDHEROERNA ÄR LIKA HÖGA, Dennis 2026-08-17: "kan vi göra följande hero
   sektioner lika stora, meny, oktoberfest, större sällskap och kontakt ... samma
   storlek som oktoberfestsidan".

   TALET ÄR MENYNS, INTE OKTOBERFESTS, och det är ett medvetet byte. Menyns hero är
   sedan tidigare fullskärm -- min-height: 100svh minus sidhuvudet -- medan
   Oktoberfests är innehållsstyrd. Uppmätt vid 1440x900 låg de 10 px isär (803 mot
   793), alltså är Oktoberfests höjd redan i praktiken en fullskärmshöjd, av en
   slump i hur mycket innehåll den bär. Att ta MENYNS regel gör alla fyra lika vid
   VARJE fönsterstorlek; att ta Oktoberfests tal som ett fast px-värde hade gjort
   dem lika på exakt en skärm och olika på alla andra, och menyn hade tappat sitt
   fullskärmsgrepp.

   VAD SOM INTE GÅR ATT LOVA: en hero kan inte vara kortare än sitt innehåll.
   Golvet garanterar att ingen hero är KORTARE än de andra, inte att ingen är
   högre. Det som Dennis faktiskt tittade på -- kontakt på 345 px mot Oktoberfest
   på 793 -- är vad golvet rättar.

   OCH SEDAN KOM TAKET, Dennis 2026-08-18: "kan vi minska höjden på heron på
   följande sidor, meny, oktoberfest, större sällskap och kontakt". Han valde
   640 px vid 1440x900, alltså --sidhero-tak: 40rem i styles.css.

   TAKET ENSAMT HADE INTE RÄCKT, och det är hela arbetet i den här ändringen. Vid
   1440x900 mätte heroernas EGET innehåll 648 (meny), 793 (Oktoberfest), 725
   (större sällskap) och 345 (kontakt). Ett tak på 640 hade alltså bara sänkt
   kontakt och lämnat de andra där de stod, och likheten ovan hade gått förlorad
   samma dag den vanns. Så innehållet krympte med -- var och en mot sitt eget mått:

     bunten (.matkar--fri)  --lyft 2,5rem -> 1,75rem, alltså 24 px mindre slack
                            runt rotationen. Samma argument som mobilregeln redan
                            gör: slacket är räknat för kortets svaj, och ett
                            mindre kort svajar mindre.
     herobuntarna           --kb 20rem -> 16,5rem, räknat ur Oktoberfests hero: den
                            bär också vimpelraden i sin padding-top, alltså 68 px
                            mindre att ge bort. Sällskapssidans bunt följde efter
                            dagen därpå, på Dennis ord -- två buntar av samma sort
                            i två lika höga heroer ska vara samma objekt.
     .hero-hel padding      --s-8 -> --s-6, 64 px tillbaka på varje hero.
     menyns padding         3,5svh -> 2,5svh, för att textspalten mäter 585 px och
                            det gamla måttet la den på 648.

   Uppmätt efteråt: alla fyra 640 vid 1440x900, och nu ÄVEN vid 1280x800 och
   1024x768, där de tidigare låg isär (703/793/725/703 respektive 677/786/725/677).
   Taket gjorde alltså likheten bredare, inte smalare.

   MENYN BEHÅLLER SIN EGEN REGEL nedan i stället för att dela klassen: dess insida
   hänger på align-content: stretch, som sträcker ramen så fotot fyller skärmen, och
   .hero-hel centrerar i stället. Samma tal, två regler -- och det är grinden som
   håller dem i synk, inte en delad rad. Se matt_heroer.mjs. */
.hero-hel {
  --topp-fall: 5.75rem;
  min-height: min(calc(100svh - var(--topp-h, var(--topp-fall)) - 1px),
                  var(--sidhero-tak));
  /* --s-6 och inte bandets --s-8: heron ska ner till taket, och 64 px luft i
     över- och underkant är det första som kan ge sig utan att någonting flyttar
     ihop sig. Innehållet är centrerat, så luften finns kvar som tomrum ändå. */
  padding-block: var(--s-6);
  display: grid;
  /* center och inte stretch: kontaktheron bär en rubrik och en mening, och ett
     stretchat rutnät hade klistrat dem mot överkanten med all luft under. */
  align-content: center;
}
@media (min-width: 52rem) {
  .hero-hel { --topp-fall: 8rem; }
}

/* MER MOBILANPASSAT, Dennis 2026-08-18: "gör så heron på oktoberfest, större
   sällskap och kontakt sidan är bättre mobilanpassat" -- ospecificerat vilket,
   så det mätbara som faktiskt skiljer dessa tre från menyheron är att de
   ALDRIG fått en mobilregel: --s-6 (32 px) i topp och botten är samma tal som
   på en 1440-skärm, och centreringen (align-content: center) lägger den luften
   ovanpå en textkolumn som redan är hela innehållet på en telefon -- två
   skärmars scroll innan bildspelet syns är priset. Detta krymper den luften;
   det byter inte ut vilket innehåll som visas eller i vilken ordning (se
   menytopp-band ovan för den sortens omtag, som denna klass inte lovar). */
@media (max-width: 51.999rem) {
  .hero-hel { padding-block: var(--s-4); }
}
/* SISTA 6 PX, Dennis 2026-08-19: sidhuvud + hero ska rymmas i 844 px utan scroll
   (390x844) -- gapet ovan (--s-5) täckte 24 av 30, kvar stod 6. --s-4 -> --s-3
   ger 8, med två px kvar som marginal (samma tolerans grinden räknar med). */
@media (max-width: 30rem) {
  .hero-hel { padding-block: var(--s-3); }
}

.menytopp-band {
  --topp-fall: 5.75rem;
  /* Minus 1px: meny-luckan.js avrundar --topp-h NEDÅT med flit (en sticky bar
     är 127,4 px hög, och en överlappning under en pixel är osynlig medan en
     glipa under en pixel inte är det). Nedåtavrundningen gör att gapet under
     sidhuvudet kan vara upp till en pixel MINDRE än vad heron räknar med, och
     då hamnar heron en pixel under vikningen. En pixel tillbaka löser det på
     rätt sida: här, inte genom att ändra en avrundning som är motiverad. */
  min-height: min(calc(100svh - var(--topp-h, var(--topp-fall)) - 1px),
                  var(--sidhero-tak));
  display: grid;
  /* stretch, inte center: ett centrerat rutnät ger sina barn exakt så mycket
     höjd som de själva ber om, och då finns ingenting att fördela till fotot.
     Med stretch fyller raden heron, ramen sträcks och bilden blir så stor som
     skärmen tillåter -- texten centreras i stället i sin egen cell. */
  align-content: stretch;
  /* Bandets egen clamp(3.5rem, 9vw, 8rem) är 128 px vid 1440 -- en sjundedel av
     en 900-skärm i ren luft, och den luften är det första som ska ge sig.
     2,5svh och inte 3,5: med taket på 40rem är textspalten det som avgör, och den
     mäter 585 px vid 1440x900. 3,5svh la heron på 648, alltså 8 px över de andra
     tre och utanför grindens tolerans på 2. */
  padding-block: clamp(0.75rem, 2.5svh, 3rem);
}

@media (min-width: 52rem) {
  .menytopp-band { --topp-fall: 8rem; }
  /* Texten mitt i sin spalt. Utan align-self klistras den mot överkanten i en
     spalt som är hela heron hög. */
  .menytopp__text { align-self: center; }
}

/* Knapparna (Lilla Moldau/Klassik/Original/Arnold) i linje med bildens
   underkant. --hunger-linje räknas av hunger.js -- centrerad kolumn mot
   centrerad ram med olika egen höjd delar bara sin MITTPUNKT, inte sina
   kanter, och glappet ändrar sig med skärmens höjd (clamp(...,svh,...) på
   ömse sidor). Ingen fast marginal håller. Utan JS är variabeln osatt och
   translate blir 0 -- samma läge som förut. */
.menytopp__text { transform: translateY(var(--hunger-linje, 0px)); }

/* Ramen är kvadratisk som fotot och har ett TAK -- men BARA i tvåspaltsformen.
   Den växte mellan versioner (410 px, sedan hela heroens höjd, sedan 727), och
   en ram som fyller allt den får är inte en ram utan en bakgrund. Måttet är
   satt, inte ärvt: kvadraten kommer från bildytan och 26rem är taket.
   Uppmätt: ramen är OFÖRÄNDRAD genom alla fyra portionerna, 416x480 på desktop
   och 342x303 på mobil. Det är bilden som byts, aldrig rutan.

   Villkoret är den staplade formens exakta negation. Utan den scopningen tog
   kvadraten över även på 833--1023 px vid låg höjd, där raden är kort och en
   416 px hög bildyta plus bildtext sköt 312 px under vikningen. En regel som
   skrivs för en form måste bära formens villkor, inte bara dess bredd. */
@media (min-width: 64rem), (min-width: 52rem) and (min-height: 851px) {
  .menytopp__ram {
    align-self: center;
    max-width: 26rem;
  }
  .menytopp__ram .ram__bildyta { aspect-ratio: 1; }
}

/* Typografin skalar med höjden också, inte bara bredden. min() tar det minsta
   av breddklampen och höjdmåttet, så en bred men låg laptop får samma omtanke
   som en telefon -- höjden är en brytpunkt.

   Luften mellan delarna är skriven i svh och inte i trappsteg. Första
   versionen hade tre @media (max-height: ...)-tier, och passningssvepet visade
   varför det är fel form: en skärm strax OVANFÖR ett steg får ingen hjälp alls
   och kan vara den som behöver den (820x951 låg 24 px över vikningen medan
   820x949 gick ihop). En clamp i svh är samma tanke utan kanter -- luften
   krymper proportionellt hela vägen och det finns ingen höjd som hamnar
   mellan två regler. */
.menytopp-band .display--stor { font-size: min(var(--t-2xl), 6svh); }

/* Ingressen skilde rubriken från väljaren, och när den flyttade ut ur heron
   stod "SERVUS IN ÖSTERREICH" och "400 gram" på varandra. Luften ska tillbaka,
   men som mellanrum och inte som en textrad man behöver hitta på.
   Mobilformen ignorerar den här regeln gratis: där är .hunger__interaktiv
   display: contents, och en låda som inte finns har inga marginaler. */
.menytopp h1 + .hunger__interaktiv { margin-top: clamp(1rem, 2.6svh, 2.25rem); }
.menytopp-band .display--stor + .lead { margin-top: clamp(0.5rem, 1.4svh, 1rem); }
.menytopp .lead { margin-bottom: clamp(0.75rem, 2svh, 1.5rem); }
.menytopp .hunger__vikt { font-size: min(clamp(3.5rem, 2rem + 8vw, 7rem), 9svh); }
.menytopp .hunger__namn { margin: var(--s-1) 0 clamp(0.5rem, 1.4svh, 1rem); }
.menytopp .hunger__replik {
  /* 3,2 em, inte 3,6: reserven finns för att repliken byts med reglaget och
     den längsta engelska raden tar tre rader, så den kan krympas men aldrig
     tas bort -- utan reserv hoppar hela heron när gästen drar. */
  min-height: 3.2em;
  margin-bottom: clamp(0.75rem, 2svh, 1.5rem);
}
.menytopp .hunger__vink { margin-bottom: clamp(0.5rem, 1.4svh, 1rem); }
.menytopp .hunger__reglage { margin-bottom: clamp(0.5rem, 1.4svh, 1rem); }
.menytopp .hunger__steg { margin-bottom: clamp(1rem, 2.6svh, 2rem); }

/* Fotot slutar bestämma heroens höjd. Bilden är kvadratisk (1600x1600) och
   drev rutnätsraden till 593 px på en 700-skärm -- högre än texten bredvid, så
   all komprimering av texten gav exakt noll. Absolut placerad står den utanför
   den inneboende storleksberäkningen: RADEN får sin höjd av texten, och fotot
   beskärs i stället för att skjuta.
   Beskuren, inte klippt -- object-fit visar mindre av fotot, den raderar
   ingenting, och det är hela skillnaden mot en max-height med overflow. */
/* Ramen är kvadratisk som källfilerna (1600x1600) och tar det MINSTA av
   spaltens bredd och radens höjd: aspect-ratio med tak i båda riktningar gör
   att en låg skärm krymper fotot i två riktningar i stället för att beskära
   det. Kvadraten kan därför aldrig spränga vikningen. */
/* Ramen fyller sin cell och BILDEN garanterar helheten, inte ramens form.
   Att göra ramen kvadratisk med aspect-ratio såg rätt ut på 1440 och skapade
   en cirkelreferens överallt annars: bredden kom ur höjden, höjden ur raden,
   raden ur innehållet. Webbläsaren bröt cirkeln på sitt eget sätt och gav 492
   px på både 833 och 1023 px bredd -- ett tal som inte hörde ihop med någon
   skärm, och som sköt reglaget under vikningen.
   Med contain på bilden är helheten garanterad av bilden själv. Det ramen inte
   fyller blir valnötspassepartout, vilket är vad en ram med mörk insida ska
   göra. Taket på bredden finns för att en 975 px bred guldram runt ett 380 px
   foto inte är en ram, det är en inramad tomhet. */
.menytopp__ram { margin-inline: auto; }

.menytopp__ram .ram__inre { grid-template-rows: minmax(0, 1fr) auto; }
.menytopp__ram .ram__inre > .ram__bildyta { grid-row: 1; }
/* HELA fotot, aldrig en beskärning. Dennis 2026-08-10: "man måste se mer utav
   bilden, helst hela bilden". Det är ingen smakfråga: fotona visar en portion
   PÅ EN TALLRIK, och hela väljaren handlar om huruvida schnitzeln får plats på
   den -- "Nu tar tallriken slut innan schnitzeln gör det". Beskär man bort
   tallrikens kant finns ingen jämförelse kvar. Uppmätt: den gamla rutan visade
   76 % av bildhöjden och klippte 135 px upptill och 112 px nedtill, alltså
   precis kanten.

   contain, inte cover: cover fyller rutan och offrar det som inte får plats,
   contain offrar rutan och behåller bilden. Och bilden ligger i FLÖDET igen --
   absolut placerad täckte den hela ramen inklusive bildtextens rad, så
   bildtexten fick en egen valnötsplatta som i sin tur låg över tallriken. */
/* ALLA fyra ligger absolut, inte bara den valda, och de tonar mellan sig.
   Dennis 2026-08-13: "just nu justeras bilderna väldigt hårt, det ska kännas
   mer smooth och mjukt".

   Bytet satt i `display`, och display kan inte tona -- portionen byttes i ett
   enda bildrute-hopp mitt under en dragrörelse som i övrigt är kontinuerlig.
   Det läser som ett fel även när det är rätt. Med alla fyra staplade blir
   bytet en övertoning i stället, och att dra genom hela reglaget blir ett
   förlopp: schnitzeln växer, den hoppar inte.

   `visibility` och inte bara `opacity`: en bild på opacity 0 ligger kvar i
   tillgänglighetsträdet, och löftet i det här blocket har hela tiden varit att
   bara den valda portionen finns där. visibility tonar inte men den VÄNTAR ut
   övertoningen (diskret vid slutet på väg ut, direkt på väg in), så trädet
   stämmer i vila utan att fadet klipps.

   Att de nu alla ligger i layouten är också vad som gör första bytet mjukt:
   display:none höll dem lazy och oladdade, så den första dragningen bytte till
   en bild som inte fanns än. */
.menytopp .hunger__bild {
  display: block;
  position: absolute;
  inset: 0;
  /* Mot överkanten. Med contain blir det som ramen inte fyller en valnötsremsa,
     och centrerad delades den i två -- en ovanför motivet och en under, där den
     lästes som ett fel snarare än som passepartout. Samlad vid underkanten
     ligger den intill bildtexten och läser som dess luft. */
  object-position: 50% 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Valnöt bakom VARJE bild, inte bara bakom ytan. Det är den här raden som gör
     övertoningen tät: med contain fyller fotot inte rutan, så en bild på halv
     opacitet slog igenom till bottnen och blandades med den. Nu bär varje bild
     sin egen mark och är en ogenomskinlig platta. Samma färg som .ram__inre
     redan har, så ingenting ser annorlunda ut i vila. */
  background: var(--valnot);
  opacity: 0;
  z-index: 0;
}

/* En ANIMATION, inte en transition, och det är hela skillnaden mellan att dra
   åt ett håll och att dra fram och tillbaka.

   En transition tonar från det värde elementet råkar ha. Den utgående bilden
   ligger kvar på 1 (se nedan), så i det ögonblick man vänder är nästa bild
   REDAN full -- det finns ingenting att tona från och den poppar fram. Uppmätt
   på vägen 1-2-3-4-3-2-1: varje steg tonade utom vändningen, som slog om på en
   bildruta. Det är precis det Dennis kände som ett hack, och exakt vid
   vändpunkten.

   En keyframe börjar alltid på 0 oavsett vad elementet stod på, och startar om
   varje gång data-aktiv flyttar hit. Vändningen blir därför likadan som varje
   annat steg.

   Linjär: två opaciteter i en övertoning ska summera till 1, annars lyser
   bottnen igenom. En mjukad kurva gör det bara så länge övertoningen får gå
   klart, vilket den mitt i ett drag aldrig gör.

   220 ms: 420 kändes trögt på just den här kontrollen. Ett reglage ska följa
   handen. */
@keyframes hunger-tona-in {
  from { opacity: 0; }
}

/* Den som just lämnade ligger kvar HELT ogenomskinlig, ett lager under den som
   tonar in. Det är hela lösningen på blekningen: den utgående tonar inte ut, den
   blir övertäckt. Uppmätt före: under ett snabbt drag genom alla fyra föll den
   sammanlagda täckningen till 0,39 och tallriken syntes som genom valnöt --
   varje bild var mitt i sin egen kurva och ingen av dem var i närheten av 1.

   Den går till full täckning omedelbart och utan egen toning: i samma ögonblick
   börjar nästa tona in ovanpå den. Tonade den i stället UT skulle vi vara
   tillbaka i samma hål. */
.menytopp .hunger__bild[data-forra="true"] {
  opacity: 1;
  z-index: 1;
}

.menytopp .hunger__bild[data-aktiv="true"] {
  opacity: 1;
  z-index: 2;
  animation: hunger-tona-in 220ms linear;
}

/* Den som ber om mindre rörelse får bytet rakt av. Ingen mellanform: en
   halverad övertoning är fortfarande en övertoning. */
@media (prefers-reduced-motion: reduce) {
  .menytopp .hunger__bild[data-aktiv="true"] { animation: none; }
}

/* Bildytan ÄR radhöjden, och bilderna ligger absolut inuti den. En bild i
   flödet bidrar med sin egen proportion till radens höjd -- ramen låg 24 px
   under vikningen på en 1440x700-laptop hur mycket texten än krympte, och
   talet ändrade sig inte av något jag gjorde med texten. min-height: 0 är det
   som tillåter raden att bli mindre än sitt innehåll. */
.ram__bildyta {
  position: relative;
  min-height: 0;
  overflow: hidden;
}
/* Bildtexten ligger kvar i flödet, ovanpå den absoluta bilden -- och behöver
   därför sin egen mark. Förut låg den på ramens valnötsbotten; när bilden blev
   absolut och täcker hela ramen hamnade den rakt på fotot, och en bildruta
   visade den ligga oläslig tvärs över schnitzeln. Text på fotografi mäts inte
   av en DOM-baserad kontrastmätare -- den svarar "bild" och går vidare -- så
   den ska inte ligga där. En solid platta gör kontrasten bestämd av paletten
   (creme på valnöt, 13,9:1) i stället för av bildrutan under. */
.menytopp__ram figcaption {
  position: relative;
  grid-row: 2;
  background: var(--valnot);
}

/* En låg och bred skärm har utrymme i SIDLED, inte i höjd. Under 850 px höjd
   delar väljaren sig i två spalter: siffran, namnet och repliken till vänster,
   reglaget, portionerna och prisraden till höger. Raderna sätts explicit --
   automatisk placering med bara grid-column angiven flyttar markören och
   lägger vinken på fel rad. */
@media (min-width: 64rem) and (max-height: 850px) {
  /* html[data-js="true"] med, inte för syns skull: regeln som slår på väljaren
     alls är `html[data-js="true"] .hunger__interaktiv { display: block }`, och
     utan värden är den specifikare än .menytopp .hunger__interaktiv. Utan
     prefixet vann display:block och spalterna blev aldrig till. */
  html[data-js="true"] .menytopp .hunger__interaktiv {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--s-6);
    align-items: start;
  }
  .menytopp .hunger__vikt   { grid-area: 1 / 1; }
  .menytopp .hunger__namn   { grid-area: 2 / 1; }
  .menytopp .hunger__replik { grid-area: 3 / 1; margin-bottom: 0; }
  .menytopp .hunger__vink    { grid-area: 1 / 2; }
  .menytopp .hunger__reglage { grid-area: 2 / 2; align-self: center; }
  .menytopp .hunger__steg    { grid-area: 3 / 2; }
  .menytopp .hunger__pris    { grid-area: 4 / 2; }
}


/* Under 850 px höjd ger luften sig, i den ordning den kan avvaras: rubrikens
   grad, marginalerna mellan väljarens delar, och replikens reserv från 3,6 till
   3,2 em -- reserven finns för att texten byts med reglaget och den längsta
   engelska repliken tar tre rader, så den kan krympas men inte tas bort.
   Tryckytorna rörs INTE: knapparnas 2,75rem är ett löfte om att gå att träffa,
   inte en marginal som råkar vara stor.

   950 och inte 850: en 1440x900-laptop är precis den skärm som var 17 px från
   att gå ihop, alltså den som mest av alla behöver hjälpen. En gräns satt vid
   850 lämnar den utanför sitt eget problem. */
/* Mobil: bilden överst, namnet över den, reglaget under ------------------- */
/* Dennis 2026-08-10, andra rundan: "på mobile ser det hemskt ut". Han hade
   rätt, och felet var mitt: han bad om noll scroll och jag optimerade precis
   det. Tio element delade 548 px av 575 utan luft. Att något RYMS har aldrig
   varit samma sak som att det är designat.

   Den första formen lade dessutom fotot BAKOM texten, och slöjan som
   kontrasten krävde (0,88-0,74) gjorde schnitzeln till en brun grumlig yta.
   Sämsta läget: ingen aptit, bara brus bakom bokstäverna. En bakgrund man inte
   kan identifiera är inte en bild.

   Hans ordning i stället, och den är bättre än min: portionens NAMN är
   rubriken över bilden, bilden är en riktig bild utan slöja, och reglaget
   ligger direkt under det det styr. Ingen text står på fotografi längre, så
   kontrasten bestäms av paletten igen i stället för av en slöja -- samma
   siffror som resten av sajten.

   Fotot tar det som blir över (1fr), och därför behöver det ingen höjdtrappa:
   på en hög telefon blir det stort, på en iPhone SE mindre, och kompositionen
   är densamma. Uppmätt utrymme till fotot: 241 px på 375, 391 px på 390.
   Ingressen och prisraden flyttade ut ur heron för att köpa det utrymmet --
   med dem kvar fick fotot 161 px, alltså ett band och inte ett fotografi.

   display: contents på textblocket och på väljaren är det som gör ordningen
   möjlig: deras barnbarn blir rutnätsbarn i .menytopp, och det är enda sättet
   att lägga bilden MELLAN namnet och reglaget när de bor i olika föräldrar. */
@media (max-width: 51.999rem),
       (max-width: 63.999rem) and (max-height: 850px) {
  /* Två kolumner, och varje helbrett element spänner BÅDA. Att bara sätta
     grid-row räckte inte: automatplaceringen la namnet och vikten i var sin
     kolumn och skapade därmed en andra kolumn som allt annat fick samsas med.
     Uppmätt resultat: ramen blev 180 px bred på en 390-skärm och rubriken
     avstavades till "ÖS-TERREICH". I ett rutnät är en oangiven kolumn ett
     beslut man överlåter åt webbläsaren. */
  /* Heron STRÄCKER sitt innehåll i stället för att centrera det. En 1fr-rad
     kan bara fördela utrymme som behållaren faktiskt HAR, och med
     align-content: center är rutnätets rad exakt så hög som sitt innehåll --
     alltså noll att fördela. Fotot fick 110 px av de 391 det var räknat för,
     och luften stod som ett tomt fält ovanför rubriken i stället.
     Ett centrerat rutnät och ett 1fr-barn är två motstridiga instruktioner. */
  /* Luften ned, bilden upp. Dennis 2026-08-10: "lägg till lite mer höjd på
     bilden så man ser mer utav den". På en skärm där allt ska rymmas är den
     höjden inte gratis -- den tas ur bandets luft och rubrikens grad, och
     ingenting av innehållet försvinner. */
  /* Ojämnt fördelat, Dennis 2026-08-19: "mellan naven och hero texten, lämna
     lite mer space ... det är för tight" -- "MENYN" mötte sidhuvudet nästan
     kant i kant. padding-block delade samma litet mått (1,6svh, 13,5 px på en
     844-hög telefon) mellan topp och botten, men bara toppen möter det fasta
     sidhuvudet -- botten möter reglaget, som redan har egen luft ovanför sig.
     Mer till toppen, mindre från botten: det mesta av ökningen flyttas dit den
     saknades i stället för att läggas till bandets totala höjd. */
  .menytopp-band {
    padding-top: clamp(1.25rem, 4.5svh, 2.5rem);
    /* + var(--s-1): halva bildramens gamla undermarginal, flyttad hit -- se
       notisen vid .menytopp__ram. Samma totalhöjd, luften bara omfördelad
       mot bottenkanten i stället för runt bilden. */
    padding-bottom: calc(clamp(0.375rem, 1svh, 0.75rem) + var(--s-1));
  }
  .menytopp-band .display--stor { font-size: min(var(--t-2xl), 5.4svh); }

  .menytopp {
    /* auto först: namnet tar sin egen bredd och vikten lägger sig direkt efter
       den i stället för att flyta ut till högerkanten och läsa som en lös
       siffra. Helbredda element spänner båda kolumnerna. */
    grid-template-columns: auto minmax(0, 1fr);
    /* 1 ögonbryn, 2 rubrik, 3 namnraden, 4 FOTOT, 5 vinken, 6 reglaget,
       7 knapparna, 8 repliken. */
    grid-template-rows: auto auto auto minmax(0, 1fr) auto auto auto auto;
    gap: 0;
  }

  .menytopp__text { display: contents; }
  html[data-js="true"] .menytopp .hunger__interaktiv { display: contents; }

  .menytopp .ogonbryn { grid-area: 1 / 1 / 2 / -1; }
  .menytopp h1 { grid-area: 2 / 1 / 3 / -1; }

  /* Namnraden. Här är PORTIONEN rubriken och vikten dess kvittens -- tvärtom
     mot desktop, där siffran är hjälten. Över en bild är det namnet man läser
     och siffran man kontrollerar. */
  .menytopp .hunger__namn {
    grid-area: 3 / 1;
    justify-self: start;
    align-self: end;
    font-size: clamp(1.5rem, 1rem + 3.4vw, 2.25rem);
    color: var(--guld-ljus);
    margin: var(--s-3) 0 var(--s-2);
  }
  .menytopp .hunger__vikt {
    grid-area: 3 / 2;
    justify-self: start;
    align-self: end;
    padding-left: var(--s-3);
    font-size: clamp(1.25rem, 0.9rem + 1.6vw, 1.75rem);
    margin: 0 0 var(--s-2);
  }
  /* "GRAM" SYNS KNAPPT, Dennis 2026-08-19: "gör gram texten större ser knappt
     vad det står". Basregeln (rad 211) sätter sub till 0.22em av siffran, och
     HÄR är siffran redan liten med flit -- namnet är hjälten i det här läget,
     vikten dess kvittens (se kommentaren ovan) -- så 0.22em av 20-28px landade
     på 4-6px, en storlek ingen kan läsa oavsett vad den sitter bredvid. Ett fast
     stycke ur sajtens egen typskala i stället för en bråkdel av ett redan litet
     tal: samma steg som sajtens vanliga bildtexter (--t-xs), aldrig mindre än
     det oavsett hur smalt fönstret blir. */
  .menytopp .hunger__vikt sub { font-size: var(--t-xs); }

  /* Ramen får sin höjd av raden, inte av bilden. min-height: 0 är det som
     tillåter en 1fr-rad att bli MINDRE än sitt innehåll -- utan den är
     minimistorleken auto och fotot skjuter ut kompositionen igen. */
  .menytopp__ram {
    grid-area: 4 / 1 / 5 / -1;
    min-height: 0;
    margin-top: var(--s-2);
    /* Dennis 2026-08-20: "flytta upp slidern och texten lite så den inte
       kramar botten kant". Halva marginalen (--s-1 av --s-2) flyttas rakt
       över till bandets padding-bottom nedan -- hela hade klistrat vinken
       mot ramens guldkant. Ingen ny höjd totalt: ett nollsummespel som
       håller varje redan uppmätt telefonstorlek (och 1023x849, som delar
       den här frågan) exakt lika säker som innan. */
    margin-bottom: var(--s-1);
    /* Storleken räknas ur BREDDEN, aldrig ur höjden. Höjddriven var svaret på
       "allt ska rymmas utan scroll", och priset visade sig på Dennis egen
       telefon: adressfältet fälls ihop medan man scrollar, viewporten växer
       60-90 px, och bilden växte med den. Uppmätt på 390 px bredd: 250 px vid
       750 px viewport, 319 vid 844, 342 vid 914. En bild som byter storlek
       medan man scrollar läser som en bugg.
       Bredden ändras inte av att ett adressfält försvinner. Fyra foton i exakt
       samma ruta är dessutom hela poängen: det enda som ska ändras när man
       drar är VILKEN schnitzel som ligger där. */
    /* 18,5rem och inte 19: vid 1023x849 låg heron 6 px över vikningen, och det
       måste lösas i BREDDEN. En höjdbaserad regel hade flippat i samma sekund
       adressfältet fälls ihop, och då är vi tillbaka i buggen som just lagats. */
    width: min(100%, 18.5rem);
    aspect-ratio: 1;
    height: auto;
    /* BÅDA riktningarna. justify-self ensamt räckte inte: rutnätets
       align-items: stretch är kvar och drog ut ramen i höjd så fort raden blev
       hög -- 312x367 vid 914 px viewport, alltså exakt samma växande igen fast
       genom en annan dörr. En kvadrat måste tacka nej till sträckning i höjd
       lika uttryckligt som i sidled. */
    justify-self: center;
    align-self: center;
  }
  .menytopp__ram .ram__inre { min-height: 0; }


  /* Bildtexten tog 130 px av en 190 px hög ram, alltså mer än fotot den
     beskriver. Den står kvar för skärmläsare och säger dessutom samma sak som
     ingressen, som nu ligger en rad under heron. Vill Dennis ha den synlig:
     ta bort regeln och räkna med att fotot blir ungefär hälften så högt. */
  .menytopp__ram figcaption {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .menytopp .hunger__vink { grid-area: 5 / 1 / 6 / -1; justify-self: start; }
  /* Dennis 2026-08-20: "ta bort knapparna lilla moldau, klassisk, orginal,
     arnold och gör schnitzel drag grejen lite större" -- på mobil är
     reglaget nu ENDA sättet att välja portion, så knapparna (rad 7) är borta
     helt (display:none, inte bara osynliga -- annars går de att tabba till
     utan att synas) och reglaget växer för att bära hela uppgiften ensamt. */
  .menytopp .hunger__reglage {
    grid-area: 6 / 1 / 7 / -1;
    max-width: none;
    --tumme-skala: 1.35;
  }
  .menytopp .hunger__steg { display: none; }
  .menytopp .hunger__replik { grid-area: 8 / 1 / 9 / -1; margin-bottom: 0; }
}

/* BILDEN VÄXTE MER, Dennis 2026-08-20 (andra omgången): "bilden kan bli
   större, ramen hela bildblocket" -- +0,75rem (19,25rem) räknat mot MIN
   headless-simulering var för försiktigt. Dennis egen telefon visade ett
   dött fält mellan bilden och reglaget: den riktiga telefonens 100svh är
   rymligare än min fasta 844 px-testruta kunde visa.

   21rem är inte gissat en andra gång -- det är taket SVEPT fram mot
   matt_menyhero.mjs (394 kontroller, alla bredd x höjd-kombinationer
   grinden känner till, inte bara telefoner). 22rem gav fyra nya
   scrollproblem vid smala SKRIVBORDSFÖNSTER (500/820 bred, 849/851 hög --
   ingen telefon är den formen, men grinden skyddar formen ändå); 26rem gav
   femton. 21rem är den högsta som fortfarande ger noll nya problem.

   BARA telefonbredd (aldrig den delade frågan med 1023x849 -- 18,5rem är
   gränsen dit, se notisen vid width ovan, orörd). */
@media (max-width: 51.999rem) {
  .menytopp__ram { width: min(100%, 21rem); }
}

/* Den riktigt låga skärmen. En iPhone SE ger 575 px under sidhuvudet och en
   1024x667-laptop 548, och där räcker det inte att skala typografin -- luften
   mellan delarna är det sista som finns att ge. Ingenting tas bort: ingressen
   krymper en grad men står kvar, och knapparnas tryckytor är orörda.

   Ingen breddgräns på själva luften. Första versionen hade `max-width: 52rem`
   här, alltså "det här är telefonregeln", och då stod 1023x667 och 1025x667
   kvar med 29 respektive 12 px scroll -- en låg laptop har exakt samma problem
   som en telefon och behöver samma svar. Höjden är villkoret. */
@media (max-height: 780px) {
  .menytopp-band { padding-block: clamp(0.4rem, 1svh, 0.75rem); }
  .menytopp .ogonbryn { margin-bottom: var(--s-2); }
  .menytopp .hunger__replik { min-height: 2.9em; }
  .menytopp .hunger__steg { margin-bottom: var(--s-1); }
  /* Ytterligare luft bort, Dennis 2026-08-18: "lilla moldau, klassisk, orginal
     arnold blocket samt texten under det" (steg + repliken) ska rymmas utan
     scroll. Uppmätt på en 360x780-skärm låg heron 31 px över vikningen även
     med reduktionerna ovan -- så marginalerna mellan namnet, ramen, vinken och
     reglaget krymper ett steg till. */
  .menytopp .hunger__namn { margin: var(--s-2) 0 var(--s-1); }
  .menytopp__ram { margin-block: var(--s-1); }
  .menytopp .hunger__vink { margin-bottom: var(--s-1); }
  .menytopp .hunger__reglage { margin-bottom: var(--s-1); }
}

/* Den KORTA telefonen (iPhone SE-klass, 375x667): 780px-reduktionen räcker
   inte längre -- uppmätt 139 px över vikningen efter den. Fotot är den enda
   posten stor nog att täcka mellanskillnaden, så det är den som ger sig här,
   aldrig gapen (de är redan botten). width är oförändrat räknad ur BREDDEN
   (se .menytopp__ram ovan, samma skäl: ett adressfält som fälls in får inte
   ändra bildens storlek). 11rem sparar 120 px mot 18,5rem-basen, vilket
   täcker de uppmätta 139 med marginal när 780px-reduktionen räknas med. */
@media (max-width: 51.999rem) and (max-height: 700px) {
  .menytopp__ram { width: min(100%, 11rem); }
}

/* Siffrans höjdtak hör bara hemma i desktopformen. I mobilformen är siffran
   namnets kvittens och redan liten, och ett svh-tak där hade blåst upp den
   till 53 px mitt i en rad som ska vara lugn. */
@media (min-width: 64rem) and (max-height: 780px) {
  .menytopp .hunger__vikt { font-size: min(clamp(3.5rem, 2rem + 8vw, 7rem), 8svh); }
}

/* Ingressen och prisraden, i eget block mellan heron och flikarna. De låg i
   heron och kostade 125 px där; här står de närmare det de handlar om. */
.menyintro {
  padding-block: clamp(1.25rem, 4vw, 2.5rem);
}

/* MER LUFT I TOPPEN PÅ MOBIL, Dennis 2026-08-18: "känns lite trångt just nu
   när texten är så tätt intill slutet av första blocket" -- ingressen satt
   direkt an mot heroens kappa (skal--valnot) med samma clamp som botten.
   Toppen får nu en egen, större reserv; botten är orörd. */
@media (max-width: 51.999rem) {
  .menyintro { padding-top: clamp(2rem, 8vw, 3rem); }
}

.menyintro .lead { margin-bottom: var(--s-2); }

.menyintro .brod { margin-bottom: var(--s-4); }

.menyintro__pris {
  font-size: var(--t-sm);
  margin: 0;
  color: var(--valnot-mjuk);
}

/* Centrerad på ALLA bredder, Dennis 2026-08-14. margin-inline: auto på styckena
   är inte dekoration: .lead och .brod har en satsbredd (38 respektive 34 rem),
   så text-align ensamt centrerar ORDEN inuti en smal låda som fortfarande står
   vid vänsterkanten. Rubriker ser centrerade ut och stycken gör det inte -- ett
   fel som bara syns i bildrutan och som ingen grind fångar. Satsbredderna står
   kvar; det är LÅDAN som flyttar till mitten, inte raderna som blir längre. */
.menyintro { text-align: center; }
.menyintro .lead,
.menyintro .brod,
.menyintro__pris { margin-inline: auto; }
