/* Middagsbladet — poster-style cookbook. Brand: deep green + tomato orange on cream.
   Colours are lifted from the logo (#074c36 / #e5532f). Light and dark. */

/* ---------------------------------------------------------------- fonts */
/* Self-hosted so the site keeps its zero-third-party, zero-dependency habit. */

@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/assets/fraunces.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/assets/fraunces-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/assets/nunito.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/assets/nunito-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------- tokens */

:root {
  --green: #074c36;
  --green-deep: #053527;
  --green-soft: #e2ede6;
  --orange: #e5532f;
  --orange-deep: #c33f1e;
  --orange-soft: #fce8de;

  --paper: #fbf6ec;
  --surface: #fffdf8;
  --ink: #241d17;
  --muted: #766a5c;
  --line: #e7dcc9;
  --head: var(--green);
  --on-dark: #fdf6ea;

  --shadow: 0 1px 2px rgb(36 29 23 / .06), 0 12px 28px -18px rgb(36 29 23 / .35);
  --shadow-lift: 0 2px 6px rgb(36 29 23 / .08), 0 26px 50px -24px rgb(36 29 23 / .45);

  --radius: 18px;
  --display: 'Fraunces', ui-serif, "Iowan Old Style", Georgia, serif;
  --sans: 'Nunito', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --wrap: 1240px;
  --gap: 3px; /* the whole point of the tile wall: almost no gutter */
}

@media (prefers-color-scheme: dark) {
  :root {
    --green: #2f8b66;
    --green-deep: #0b1f18;
    --green-soft: #12291f;
    --orange: #ff7a50;
    --orange-deep: #ff9573;
    --orange-soft: #2c1810;

    --paper: #10130f;
    --surface: #191d18;
    --ink: #f2e9db;
    --muted: #a99c8b;
    --line: #2b3129;
    --head: #f6ecdd;

    --shadow: 0 1px 2px rgb(0 0 0 / .5), 0 12px 28px -18px rgb(0 0 0 / .8);
    --shadow-lift: 0 2px 6px rgb(0 0 0 / .55), 0 26px 50px -24px rgb(0 0 0 / .9);
  }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* height:auto hör IHOP med max-width. Utan den behåller en bild sitt
   height-attribut när bredden kläms av spalten, och blir utdragen — vilket
   den blev så fort bilderna i löptexten fick srcset. Attributen finns kvar
   för att reservera plats innan bilden hämtats. */
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }

/* `overflow-wrap` är GOLVET och inte formgivningen: det bryter aldrig ett ord
   som får plats, bara ett som annars hade stuckit ut ur sin spalt. Svenskan
   levererar gott om sådana — "Jämställdhetsmyndigheten" satt i 2,3 rem är 486 px
   och telefonens textspalt 351 px — och rubrikerna hade ingen sådan regel alls
   utanför tidningssidan, så de stack ut och doldes av `overflow-x: hidden` på
   body. Att den doldes är värre än att den syntes: rubriken var avklippt utan
   att något såg trasigt ut. Avstavningen som gör brytningen SNYGG står längre
   ned, vid den bredd där den behövs. */
h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  font-variation-settings: 'SOFT' 60, 'WONK' 1, 'opsz' 100;
  line-height: 1.05;
  letter-spacing: -0.015em;
  color: var(--head);
  text-wrap: balance;
  overflow-wrap: break-word;
}

/**
 * Avstavning bara där spalten är smalare än orden — inte överallt.
 *
 * `hyphens: auto` avstavar när det förbättrar radbrytningen, inte bara när ett
 * ord spräcker spalten. På en bred skärm ger det avstavade rubriker helt i
 * onödan, vilket är precis det fel ettans `text-wrap: pretty` finns för att
 * undvika. Under 700 px är förhållandet det omvända: där ÄR spalten smalare än
 * de långa sammansättningarna, och valet står mellan en avstavning och ett ord
 * brutet mitt itu utan bindestreck.
 *
 * Sidan är `lang="sv"`, så brytpunkterna följer svenska ordled.
 */
@media (max-width: 700px) {
  h1, h2, h3, h4 { hyphens: auto; }
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--orange); color: #fff; padding: .75rem 1rem; border-radius: 0 0 10px 0;
}
.skip:focus { left: 0; }

:focus-visible { outline: 3px solid var(--orange); outline-offset: 2px; border-radius: 6px; }

/* A candy stripe across the very top — sets the tone before anything loads. */
.ribbon {
  height: 6px;
  background: repeating-linear-gradient(
    90deg,
    #074c36 0 26px, #e5532f 26px 52px, #f2a33c 52px 78px
  );
}

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1.5px solid var(--line);
}

/* `viewport-fit=cover` i huvudet betyder att sidan ritas UNDER telefonens
   hörn och hemknappsrad. Utan `env()` hamnar loggan bakom kameraön så snart
   luren vrids till liggande — måttet är 0 på allt annat, så regeln kostar
   ingenting där den inte behövs. `max()` gör att den vanliga paddingen
   fortfarande gäller när insatsen är mindre än den. */
.bar {
  max-width: var(--wrap); margin: 0 auto;
  padding: .55rem clamp(.85rem, 3vw, 2rem);
  padding-left: max(clamp(.85rem, 3vw, 2rem), env(safe-area-inset-left));
  padding-right: max(clamp(.85rem, 3vw, 2rem), env(safe-area-inset-right));
  display: flex; align-items: center; gap: clamp(.6rem, 2.5vw, 1.75rem);
}

/* Header runs the lockup horizontally — spoon beside wordmark — so the
   wordmark stays big without making the sticky bar tall. */
.brand {
  display: flex; align-items: center; gap: .55rem;
  flex: 0 0 auto; line-height: 0; text-decoration: none;
}
.brand-mark {
  height: clamp(26px, 3.4vw, 34px); width: auto;
  transform-origin: 70% 60%;
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1);
}
.brand-word { height: clamp(21px, 2.7vw, 27px); width: auto; }
.brand:hover .brand-mark { transform: rotate(-14deg) scale(1.06); }

@media (max-width: 400px) { .brand-mark { display: none; } }

/* Vinjetten: kategorins namn intill loggan, skilt från den med ett orange
   streck — tidningens sektionsnamn i huvudet i stället för ett rubrikblock som
   trycker ner ettan. Sätt i samma serif som rubrikerna, för den ÄR sidans
   rubrik; att den står i huvudet gör den inte till en meny. */
.brand-section {
  display: flex; align-items: center; gap: clamp(.5rem, 1.6vw, .8rem);
  flex: 0 1 auto; min-width: 0;
  font-family: var(--display); font-weight: 800;
  font-variation-settings: 'SOFT' 40, 'WONK' 0, 'opsz' 72;
  font-size: clamp(1.05rem, 2.4vw, 1.5rem);
  line-height: 1; letter-spacing: -.01em;
  color: var(--head); white-space: nowrap;
  /* Vinjetten ger vika för menyn i stället för att trycka ut den ur huvudet.
     Ingen ellips: texten är en anonym flexruta bredvid ::before-strecket, och
     `text-overflow` biter inte på en sådan. Att den klipps är ändå rätt
     avvägning — kategorinamnet står också i menyn. */
  overflow: hidden;
}
.brand-section::before {
  content: ""; flex: 0 0 auto; width: 2px; height: 1.35em;
  border-radius: 2px; background: var(--orange);
}
/* Nere vid telefonbredd får menyn gå före: hellre ett huvud på två rader än ett
   som spänner isär sig. Vinjetten står kvar — det är den som säger var man är. */
@media (max-width: 560px) {
  .brand-section { font-size: 1rem; gap: .45rem; }
  .brand-section::before { height: 1.2em; }
}

.foot-logo { display: block; line-height: 0; }
.foot-logo img { height: clamp(70px, 11vw, 96px); width: auto; }

/* Menyn får RADBRYTA. Den hade `margin-left: auto` och ingen `flex-wrap`, så
   med en vinjett bredvid loggan och fyra kategorier sprängde den huvudet i
   sidled på en telefon: logga 113 px + vinjett ~80 + meny ~240 = 433 px i en
   ruta på 390. Att den bryter är alltid bättre än att den skjuts ut ur bilden. */
.nav {
  display: flex; flex-wrap: wrap; justify-content: flex-end;
  gap: .25rem clamp(.5rem, 2vw, 1.1rem); margin-left: auto;
}
.nav a {
  text-decoration: none; font-size: .95rem; font-weight: 800; color: var(--ink);
  padding: .35rem .6rem; border-radius: 999px;
  transition: color .15s, background .15s;
}
.nav a:hover { color: #fff; background: var(--orange); }
@media (prefers-color-scheme: dark) { .nav a:hover { color: #1a0d07; } }

.search { display: flex; align-items: center; position: relative; }
.search input {
  font: inherit; font-size: .95rem; font-weight: 600;
  background: var(--surface); color: var(--ink);
  border: 1.5px solid var(--line); border-radius: 999px;
  padding: .48rem 2.4rem .48rem 1rem; width: clamp(7.5rem, 17vw, 14rem);
  transition: border-color .15s, box-shadow .15s;
}
.search input::placeholder { color: var(--muted); font-weight: 600; }
.search input:focus {
  border-color: var(--orange); box-shadow: 0 0 0 4px var(--orange-soft); outline: none;
}
.search button {
  position: absolute; right: .28rem; background: none; border: 0; cursor: pointer;
  padding: .35rem; color: var(--muted); display: grid; place-items: center;
}
.search button svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round;
}
.search button:hover { color: var(--orange); }

@media (max-width: 760px) {
  .bar { flex-wrap: wrap; row-gap: .5rem; }
  .nav { margin-left: auto; order: 2; }
  .search { order: 3; flex: 1 1 100%; }
  /**
   * 16px, inte 15,2. Under 16 px ZOOMAR iOS Safari in hela sidan när fältet får
   * fokus, och zoomar aldrig ut igen — läsaren står kvar på en sida som ligger
   * halvvägs utanför skärmen och får panorera tillbaka för hand. Det är
   * webbläsarens läsbarhetsskydd och går inte att stänga av med annat än
   * gradtalet självt; `user-scalable=no` skulle göra det, men det tar bort
   * nypzoomen för alla som faktiskt behöver den.
   *
   * Samma tal gäller varje fält på sajten — här finns bara det ena.
   */
  .search input { width: 100%; font-size: 16px; }
}

/**
 * Tumme, inte muspekare.
 *
 * `pointer: coarse` frågar efter INMATNINGSSÄTTET och inte efter bredden, vilket
 * är det som faktiskt avgör saken: en surfplatta i liggande läge är bred och
 * styrs ändå med fingret, och en smal webbläsarruta på en dator är det
 * omvända. 44 px är Apples mått och ungefär vad en tumme träffar säkert.
 *
 * Bara höjden sätts, aldrig utseendet: knapparna ser likadana ut, de blir bara
 * möjliga att träffa.
 */
@media (pointer: coarse) {
  /* 16 px överallt där man skriver, av samma skäl som i blocket ovanför — men
     på INMATNINGSSÄTT och inte på bredd: en surfplatta i liggande läge är
     bredare än 760 px och zoomar likafullt. */
  .search input { font-size: 16px; }
  .nav a { padding-block: .6rem; }
  .search button { padding: .7rem; }
  .foot-inner nav a { padding: .5rem .35rem; }
  .page-link { padding: .8rem 1.4rem; }
  .reset-ings { padding: .65rem 1.2rem; }
}

/* ------------------------------------------------------------- kickers */

.kicker {
  margin: 0; font-size: .78rem; font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: var(--orange);
  display: flex; align-items: center; gap: .55rem;
}
.kicker::after {
  content: ""; flex: 0 0 2.2rem; height: 3px; border-radius: 3px;
  background: currentColor; opacity: .55;
}
.kicker.center { justify-content: center; }
.kicker.center::before {
  content: ""; flex: 0 0 2.2rem; height: 3px; border-radius: 3px;
  background: currentColor; opacity: .55;
}

.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--orange); color: #fff;
  padding: .8rem 1.6rem; border-radius: 999px;
  font-weight: 800; font-size: 1rem; text-decoration: none;
  box-shadow: 0 6px 0 -1px var(--orange-deep);
  transition: transform .16s, box-shadow .16s, background .16s;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 8px 0 -1px var(--orange-deep); }
.btn:active { transform: translateY(2px); box-shadow: 0 3px 0 -1px var(--orange-deep); }

/* ---------------------------------------------------------------- hero */

.hero {
  display: grid;
  border-bottom: 1.5px solid var(--line);
  background: var(--surface);
}

.hero-media {
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 4 / 3; background: var(--green-soft);
}
.hero-img { width: 100%; height: 100%; object-fit: cover; }
.hero-media:hover .hero-img { transform: scale(1.03); }
.hero-img { transition: transform .6s ease; }

/* Rotated sticker over the photo — the “fun” cue that a blog card never has. */
.sticker {
  position: absolute; top: clamp(.75rem, 2.5vw, 1.6rem); left: clamp(.75rem, 2.5vw, 1.6rem);
  background: var(--orange); color: #fff;
  font-weight: 800; font-size: .74rem; letter-spacing: .14em; text-transform: uppercase;
  padding: .45rem .9rem; border-radius: 999px; transform: rotate(-4deg);
  box-shadow: 0 6px 18px -6px rgb(0 0 0 / .5);
}

.hero-text {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1rem;
  padding: clamp(1.75rem, 5vw, 4rem) clamp(1.15rem, 5vw, 4rem);
  /* faint dot texture, so the panel does not read as an empty content box */
  background-image: radial-gradient(var(--line) .9px, transparent 1px);
  background-size: 18px 18px;
}
.hero-title {
  font-size: clamp(2.3rem, 6vw, 4.4rem);
  font-variation-settings: 'SOFT' 80, 'WONK' 1, 'opsz' 144;
  margin: 0;
}
.hero-title a { text-decoration: none; }
.hero-title a:hover { color: var(--orange); }
.hero-intro {
  margin: 0; max-width: 40ch; color: var(--muted);
  font-size: clamp(1rem, 1.6vw, 1.18rem); text-wrap: pretty;
}

@media (min-width: 900px) {
  .hero { grid-template-columns: 1.05fr 1fr; align-items: stretch; }
  .hero-media { grid-column: 2; grid-row: 1; aspect-ratio: auto; min-height: 32rem; }
  .hero-text { grid-column: 1; grid-row: 1; justify-content: center; }
}

/* ------------------------------------------------------------- sections */

.section {
  max-width: var(--wrap); margin: 0 auto;
  padding: clamp(2.25rem, 5vw, 4rem) clamp(1rem, 4vw, 2rem);
}
.section.narrow { max-width: 46rem; }
.section.bleed { max-width: none; padding-left: 0; padding-right: 0; }

.section-head {
  display: flex; flex-direction: column; gap: .55rem; align-items: center;
  text-align: center; margin-bottom: clamp(1.25rem, 3vw, 2.25rem);
  padding: 0 clamp(1rem, 4vw, 2rem);
}
.section-head h1, .section-head h2 {
  font-size: clamp(1.9rem, 4.4vw, 3rem);
  font-variation-settings: 'SOFT' 80, 'WONK' 1, 'opsz' 144;
}
.section-sub { margin: 0; color: var(--muted); font-size: 1rem; max-width: 48ch; }

/* ----------------------------------------------------------- tile wall */

.wall {
  display: grid;
  gap: var(--gap);
  grid-auto-flow: dense;
  grid-template-columns: repeat(2, 1fr); /* phones always get a two-up mosaic */
  /* Shows through the 3px gutters, and fills the empty cells of a short last
     row — so it has to be the page colour, not a darker rule colour. */
  background: var(--paper);
  border-block: 1.5px solid var(--line);
}
@media (min-width: 560px) {
  .wall { grid-template-columns: repeat(auto-fill, minmax(min(33.333%, 260px), 1fr)); }
}

.tile {
  position: relative; overflow: hidden;
  aspect-ratio: 1 / 1; background: var(--green-deep);
  isolation: isolate;
}
/* Every eighth tile goes wide, so the wall reads as a mosaic and not a table. */
@media (min-width: 760px) {
  .tile:nth-child(8n + 3) { grid-column: span 2; aspect-ratio: 2 / 1; }
}

.tile-link {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  justify-content: flex-end; text-decoration: none; color: var(--on-dark);
  padding: clamp(.8rem, 1.8vw, 1.35rem);
}
.tile-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  z-index: -2; transition: transform .55s cubic-bezier(.2, .7, .3, 1), filter .35s;
}
.tile-link::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top,
    rgb(5 20 14 / .92) 0%, rgb(5 20 14 / .62) 34%, rgb(5 20 14 / .12) 66%, rgb(5 20 14 / 0) 100%);
  transition: opacity .3s;
}
.tile:hover .tile-img { transform: scale(1.07); }
.tile:hover .tile-link::before { opacity: .88; }

.tile-title {
  color: var(--on-dark);
  font-size: clamp(1.02rem, 1.55vw, 1.35rem);
  font-variation-settings: 'SOFT' 90, 'WONK' 1, 'opsz' 60;
  line-height: 1.15;
  text-shadow: 0 2px 14px rgb(0 0 0 / .45);
}
.tile:nth-child(8n + 3) .tile-title { font-size: clamp(1.1rem, 2.1vw, 1.8rem); }

.tile-note {
  margin: .35rem 0 0; font-size: .78rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase;
  color: rgb(253 246 234 / .74);
  display: flex; align-items: center; gap: .4rem;
}
.tile-note::before {
  content: ""; width: .4rem; height: .4rem; border-radius: 50%; background: var(--orange);
}
/* Orange bar wipes in along the bottom edge on hover. */
.tile-link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 5px;
  background: var(--orange); transform: scaleX(0); transform-origin: left;
  transition: transform .3s ease;
}
.tile:hover .tile-link::after { transform: scaleX(1); }

.img-fallback {
  position: absolute; inset: 0; z-index: -2;
  background: linear-gradient(135deg, var(--green) 0%, var(--green-deep) 55%, var(--orange-deep) 100%);
}

.empty { color: var(--muted); text-align: center; padding: 2rem 1rem; }
.empty a:not(.btn) { color: var(--orange); font-weight: 800; }

/* --------------------------------------------------------------- pager */

.pager {
  display: flex; align-items: center; justify-content: center; gap: 1rem;
  flex-wrap: wrap; margin: clamp(1.75rem, 4vw, 2.75rem) auto 0;
  padding: 0 clamp(1rem, 4vw, 2rem);
}
.page-link {
  text-decoration: none; font-weight: 800; color: var(--green);
  padding: .6rem 1.25rem; border: 2px solid var(--green); border-radius: 999px;
  background: transparent; transition: background .15s, color .15s, transform .15s;
}
.page-link:hover { background: var(--green); color: var(--on-dark); transform: translateY(-2px); }

/* -------------------------------------------------------------- recipe */

.recipe-hero { position: relative; background: var(--green-deep); }
.recipe-hero-img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; max-height: 76vh; }
.recipe-hero-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgb(5 20 14 / .93) 0%, rgb(5 20 14 / .55) 38%, rgb(5 20 14 / .08) 72%);
}
.recipe-hero-text {
  position: absolute; inset-inline: 0; bottom: 0; color: var(--on-dark);
  max-width: var(--wrap); margin: 0 auto;
  padding: clamp(1.4rem, 4vw, 3.25rem) clamp(1rem, 4vw, 2rem);
  padding-left: max(clamp(1rem, 4vw, 2rem), env(safe-area-inset-left));
  padding-right: max(clamp(1rem, 4vw, 2rem), env(safe-area-inset-right));
  display: flex; flex-direction: column; gap: .7rem; align-items: flex-start;
}
.recipe-hero-text h1 {
  font-size: clamp(2rem, 5.6vw, 4rem); color: var(--on-dark);
  font-variation-settings: 'SOFT' 90, 'WONK' 1, 'opsz' 144;
  text-shadow: 0 2px 26px rgb(0 0 0 / .5);
}
.recipe-hero-text .kicker { color: #ffc9ab; }

@media (min-width: 820px) {
  .recipe-hero-img { aspect-ratio: 16 / 9; }
}

.lede {
  max-width: 44rem; margin: clamp(1.6rem, 4vw, 2.6rem) auto 0;
  padding: 0 clamp(1rem, 4vw, 2rem);
  font-family: var(--display);
  font-variation-settings: 'SOFT' 60, 'WONK' 0, 'opsz' 40;
  font-size: clamp(1.12rem, 2.2vw, 1.38rem); line-height: 1.55;
  color: var(--ink); text-wrap: pretty;
}

.recipe-cols {
  max-width: var(--wrap); margin: 0 auto;
  padding: clamp(1.75rem, 4vw, 3rem) clamp(1rem, 4vw, 2rem) clamp(2rem, 5vw, 4rem);
  display: grid; gap: clamp(1.5rem, 3.5vw, 3rem);
  align-items: start;
}

@media (min-width: 940px) {
  .recipe-cols { grid-template-columns: minmax(18rem, 22rem) 1fr; }
  .ingredients { position: sticky; top: 6rem; }
}

.recipe-cols h2 {
  font-size: 1.6rem; margin-bottom: 1rem;
  font-variation-settings: 'SOFT' 90, 'WONK' 1, 'opsz' 72;
}

/* ---- ingredients */

.ingredients {
  background: var(--surface); border: 2px solid var(--green);
  border-radius: var(--radius); padding: clamp(1.15rem, 3vw, 1.7rem);
  box-shadow: 6px 6px 0 -1px var(--green-soft);
}
.ing-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ing { border-bottom: 1px dashed var(--line); }
.ing:last-child { border-bottom: 0; }
.ing label {
  display: flex; align-items: flex-start; gap: .8rem; cursor: pointer;
  padding: .65rem .15rem; /* generous tap target for cooking with messy hands */
  font-weight: 600; transition: color .15s;
}
.ing-check { position: absolute; opacity: 0; width: 0; height: 0; }
.ing label::before {
  content: ""; flex: 0 0 auto; width: 1.35rem; height: 1.35rem; margin-top: .18rem;
  border: 2px solid var(--line); border-radius: 7px; background: var(--paper);
  transition: background .15s, border-color .15s;
}
.ing-check:checked + label {
  color: var(--muted); text-decoration: line-through; text-decoration-color: var(--orange);
}
.ing-check:checked + label::before {
  background: var(--orange) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center / 0.95rem no-repeat;
  border-color: var(--orange);
}
.ing-check:focus-visible + label::before { outline: 3px solid var(--orange); outline-offset: 2px; }

.reset-ings {
  margin-top: 1rem; font: inherit; font-size: .85rem; font-weight: 800;
  background: none; border: 2px solid var(--line); border-radius: 999px;
  padding: .45rem 1.1rem; color: var(--muted); cursor: pointer;
}
.reset-ings:hover { border-color: var(--orange); color: var(--orange); }

/* ---- steps */

.steps { list-style: none; margin: 0; padding: 0; }
.step {
  display: flex; gap: clamp(.9rem, 2vw, 1.4rem);
  padding: 1.05rem 0; border-bottom: 1px dashed var(--line);
}
.step:last-child { border-bottom: 0; }
.step p { margin: 0; font-size: 1.075rem; line-height: 1.7; text-wrap: pretty; }
.step-n {
  flex: 0 0 auto; width: 2.5rem; height: 2.5rem; border-radius: 50%;
  background: var(--orange); color: #fff;
  font-family: var(--display); font-size: 1.2rem; font-weight: 800;
  font-variation-settings: 'SOFT' 100, 'WONK' 1, 'opsz' 40;
  display: grid; place-items: center;
}
/* Texten och stegets bilder ligger i samma spalt, till höger om siffran.
   min-width: 0 så en bred bild inte spränger flexraden. */
.step-body { flex: 1 1 auto; min-width: 0; }

/* ---- processbilder */

.step-figure { margin: 1rem 0 .35rem; }
.step-figure img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius); box-shadow: var(--shadow);
  background: var(--green-soft); /* syns medan bilden laddar */
}
.step-figure figcaption {
  margin-top: .55rem; font-size: .92rem; line-height: 1.5;
  color: var(--muted); text-wrap: pretty;
}

/* Bilderna sist på sidan: en spalt, samma läsmått som prosan. */
.recipe-gallery {
  max-width: 44rem; margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2rem) clamp(2.5rem, 6vw, 4rem);
  display: flex; flex-direction: column; gap: clamp(1.4rem, 3vw, 2.2rem);
}
.recipe-gallery .step-figure { margin: 0; }
/* Prosainlägg har redan en botteninsats i .prose — dubbla den inte. */
.prose + .recipe-gallery { padding-top: 0; }

.related { border-top: 0; }

/* --------------------------------------------------------------- prose */

.prose, .page {
  max-width: 44rem; margin: 0 auto;
  padding: clamp(1.6rem, 4vw, 2.75rem) clamp(1rem, 4vw, 2rem) clamp(2.5rem, 6vw, 4rem);
}
/* A page already provides the column, so its prose must not inset again. */
.page .prose { max-width: none; padding: 0; }
.page h1 {
  font-size: clamp(2rem, 5vw, 3rem); margin: .5rem 0 1.25rem;
  font-variation-settings: 'SOFT' 80, 'WONK' 1, 'opsz' 144;
}

/* ---- fristående sida i två spalter (se simplePage() i app/render.js)

   Vänsterspalten behåller prosans läsmått — 44rem är valt för att raderna ska
   gå att läsa, och en bredare sida får inte göra dem längre. Sidan blir alltså
   bredare genom att marginalspalten LÄGGS TILL, inte genom att texten sträcks.
   Under 900px faller allt tillbaka i en spalt och marginalen hamnar sist. */
.page-split { max-width: 72rem; }
.page-cols { display: grid; gap: clamp(1.6rem, 4vw, 3rem); align-items: start; }
/* Marginalspalten har ett TAK i rem och inte bara en andel: bilden är en
   inskannad förstasida på 274 pixlar, och en spalt som växer med fönstret hade
   skalat upp den tills pappret blev grötigt. */
@media (min-width: 900px) {
  .page-cols { grid-template-columns: minmax(0, 1.6fr) minmax(14rem, 20rem); }
}
.page-cols .prose { max-width: 44rem; }

.page-aside-inner {
  display: flex; flex-direction: column; gap: clamp(1.2rem, 3vw, 1.8rem);
}
.page-aside figure { margin: 0; }
/* `width: auto` och inte `100%`: i en spalt ligger bilden i sitt eget mått. En
   inskannad förstasida på 274 pixlar utsträckt över en hel telefonskärm är
   gröt, och att spara plats genom att sudda ut bilden är ingen besparing. */
.page-aside img {
  width: auto; max-width: 100%; height: auto;
  border-radius: var(--radius); box-shadow: var(--shadow);
  background: var(--green-soft);
}

/**
 * Bilden slutar där texten slutar.
 *
 * Marginalspalten lyfts ur flödet — `position: absolute` inuti en `relative`
 * spalt — så att RADENS höjd bestäms av textspalten ensam. Utan det blir raden
 * så hög som bilden själv vill vara, och den kan aldrig krympa till textens
 * höjd: bilden skulle definiera det mått den sedan skulle rätta sig efter.
 *
 * Bilden får `height: 100%` och `width: auto` — alltså INTE `object-fit`. Med
 * object-fit hade elementets ruta fortsatt vara full spaltbredd och bilden
 * legat inklämd i den med en tom remsa bredvid, och remsan hade burit
 * bakgrunden, hörnradien och skuggan som hör till pappret. Nu följer bredden av
 * höjden genom bildens egna proportioner, så rutan är bilden. Beskuren blir den
 * aldrig: en förstasida från 1892 får inte klippas för layoutens skull.
 *
 * Blir texten längre än bilden kan fylla stannar bilden vid sin naturliga
 * bredd i stället för att skalas upp till gröt, och slutar då före texten. Det
 * är den ärliga gränsen: ett original på 274 pixlar kan inte bli större.
 *
 * `min-height` är golvet för en riktigt kort sida, så bilden inte pressas till
 * en strimma.
 */
@media (min-width: 900px) {
  .page-aside { position: relative; align-self: stretch; min-height: 18rem; }
  .page-aside-inner { position: absolute; inset: 0; }
  .page-aside figure {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column; align-items: flex-start;
  }
  .page-aside img { flex: 1 1 auto; min-height: 0; height: 100%; width: auto; max-width: 100%; }
}
.page-aside figcaption {
  margin-top: .6rem; font-size: .88rem; line-height: 1.5;
  color: var(--muted); text-wrap: pretty;
}

/* Utgivarrutan: tidningens redaktionsruta. Den ska gå att hitta med fingret på
   en gång — det är den ansvarige utgivaren en läsare letar efter — men den är
   inte sidans huvudtext, så den är satt mindre och i sajtens sans. */
.colophon {
  margin-top: clamp(.4rem, 2vw, 1rem);
  max-width: 44rem;
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-left: 4px solid var(--orange);
  border-radius: calc(var(--radius) - 6px);
  padding: clamp(.9rem, 2.5vw, 1.2rem) clamp(1rem, 2.5vw, 1.3rem);
}
.colophon p { margin: 0; font-size: .95rem; line-height: 1.6; text-wrap: pretty; }
.colophon strong { font-weight: 700; }
.colophon a { color: var(--orange); font-weight: 700; text-underline-offset: 3px; }
.prose p { margin: 0 0 1.15rem; text-wrap: pretty; }
.prose h2, .prose h3 { margin: 2.2rem 0 .8rem; font-size: 1.6rem; }
.prose ul, .prose ol { padding-left: 1.3rem; margin: 0 0 1.15rem; }
.prose li { margin-bottom: .45rem; }
.prose img { border-radius: var(--radius); margin: 1.6rem 0; box-shadow: var(--shadow); }
.prose a { color: var(--orange); font-weight: 700; text-underline-offset: 3px; }
.prose blockquote {
  margin: 1.6rem 0; padding: .35rem 0 .35rem 1.2rem;
  border-left: 4px solid var(--orange); color: var(--muted);
  font-family: var(--display); font-size: 1.2rem;
}

/* --------------------------------------------------------- search page */

.search.big { max-width: 36rem; margin: 0 auto 2.5rem; gap: .6rem; }
.search.big input {
  width: 100%; padding: .95rem 1.3rem; border-radius: 999px; font-size: 1.05rem;
  border-width: 2px;
}
.search.big button {
  position: static; background: var(--orange); color: #fff; border-radius: 999px;
  padding: .95rem 1.7rem; font: inherit; font-weight: 800; font-size: 1rem;
  box-shadow: 0 5px 0 -1px var(--orange-deep);
}
.search.big button:hover { background: var(--orange-deep); color: #fff; }

/* -------------------------------------------------------------- footer */

.site-footer { background: var(--green-deep); color: var(--on-dark); margin-top: auto; }
/* Sidfoten är sidans sista rad och ligger därmed vid telefonens hemknappsrad.
   Botteninsatsen LÄGGS TILL den vanliga luften i stället för att ersätta den —
   det är en remsa som ska hållas fri, inte ett mått som ska ta över. */
.foot-inner {
  max-width: var(--wrap); margin: 0 auto;
  padding: clamp(2.25rem, 5vw, 3.5rem) clamp(1rem, 4vw, 2rem);
  padding-bottom: calc(clamp(2.25rem, 5vw, 3.5rem) + env(safe-area-inset-bottom));
  padding-left: max(clamp(1rem, 4vw, 2rem), env(safe-area-inset-left));
  padding-right: max(clamp(1rem, 4vw, 2rem), env(safe-area-inset-right));
  display: grid; gap: 1.4rem; justify-items: center; text-align: center;
}
.foot-tag {
  margin: 0; font-family: var(--display); font-size: 1.15rem;
  font-variation-settings: 'SOFT' 80, 'WONK' 1, 'opsz' 40;
  color: rgb(253 246 234 / .85);
}
.foot-inner nav { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.4rem; }
.foot-inner nav a {
  color: rgb(253 246 234 / .8); text-decoration: none; font-weight: 700; font-size: .95rem;
}
.foot-inner nav a:hover { color: var(--orange); }
.foot-note { margin: 0; color: rgb(253 246 234 / .5); font-size: .82rem; }

/* ------------------------------------------------------------ niceties */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .tile:hover .tile-img, .brand:hover img, .hero-media:hover .hero-img { transform: none; }
}

/* --------------------------------------------------------------- källor */

/**
 * Källistan under en nyhetsartikel.
 *
 * Samma läsmått som prosan, tydligt avskild men underordnad: den ska gå att
 * kontrollera, inte konkurrera med texten. Bara källor märkta 'outlet' hamnar
 * här — se sourceList() i app/render.js.
 */
.sources {
  max-width: 44rem;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2rem) clamp(2.5rem, 6vw, 4rem);
}
.sources h2 {
  font-family: var(--sans);
  font-size: .82rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 .7rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}
.sources ul { list-style: none; padding: 0; margin: 0; }
.sources li {
  margin: 0 0 .5rem;
  font-size: .95rem;
  color: var(--muted);
  text-wrap: pretty;
}
.sources a { color: var(--orange); font-weight: 700; text-underline-offset: 3px; }

/* Prosan och galleriet bär redan sin understa luft; annars blir den dubbel. */
.prose + .sources,
.recipe-gallery + .sources { padding-top: 0; }

/* =========================================================== utskriften ===
 *
 * Ett recept på papper är inte sajten i gråskala. Det är ett eget format med
 * en egen uppgift: att ligga på bänken bredvid skärbrädan och gå att läsa på en
 * armlängds avstånd, med skitiga händer och utan att man kan trycka på något.
 *
 * DET SOM VAR TRASIGT, och som är skälet till att blocket skrevs om: hjälten
 * klipptes med `max-height: 8cm; overflow: hidden`, och rubriken ligger
 * `position: absolute; bottom: 0` OVANPÅ bilden. Klippningen tar alltså bort
 * nederkanten — alltså precis rubriken. Ett utskrivet recept saknade sitt eget
 * namn, och det syntes inte på skärmen därför att skärmen inte klipper.
 *
 * Lösningen är inte ett mindre klipp utan att sluta lägga texten ovanpå bilden:
 * på papper står rubriken som rubrik, före bilden, i svart på vitt.
 *
 * Färg: webbläsare tar bort bakgrunder i utskrift som standard, och sajtens
 * märken är byggda av bakgrunder — den orangea sifferrondellen blir vit text på
 * vitt papper. Varje sådant märke ritas därför om med en KANT i stället, som
 * alltid skrivs ut. Det är också billigare bläck, vilket är hela skälet till att
 * webbläsaren gör som den gör.
 */
@media print {
  @page { margin: 1.6cm; }

  /* Grundfärgen. Sajtens variabler används inte här: mörkt läge får inte kunna
     följa med ut på pappret och skriva ut en svart sida. */
  body {
    background: #fff; color: #000;
    font-size: 11pt; line-height: 1.45;
  }
  h1, h2, h3, h4 { color: #000; }
  a { color: #000; text-decoration: none; }

  /* Skärmens navigering, och allt som är en uppmaning att trycka någonstans.
     `.skip` ligger på `left: -9999px` och hade annars gjort pappret 9999 px
     brett — den är osynlig på skärmen, inte borta. */
  .ribbon, .site-header, .site-footer, .skip,
  .related, .pager, .reset-ings, .sticker,
  .search, .recipe-hero-scrim { display: none !important; }

  /* ---- hjälten: rubriken FÖRE bilden, inte ovanpå den */

  /* Bilden är kvar men underordnad: den säger vad rätten ska bli, den är inte
     receptet. `order` flyttar den efter texten utan att röra HTML:en — bilden
     står först i uppmärkningen därför att den på skärmen ligger under texten. */
  .recipe-hero {
    background: none; position: static;
    display: flex; flex-direction: column;
  }
  .recipe-hero-text {
    order: 1; position: static; color: #000; padding: 0; margin: 0 0 .4cm;
    max-width: none; display: block;
  }
  .recipe-hero-img { order: 2; max-height: 7cm; width: auto; max-width: 100%; }
  .recipe-hero-text h1 {
    font-size: 24pt; color: #000; text-shadow: none;
    line-height: 1.1; margin: 0 0 .15cm;
  }
  .recipe-hero-text .kicker { color: #000; font-size: 8pt; margin: 0 0 .1cm; }
  /* Strecken kring etiketten är ren dekor och ritas som bakgrundsfärg. */
  .kicker::before, .kicker::after { display: none; }

  /* Adressen till receptet. Utan den är ett utskrivet blad en återvändsgränd:
     man kan laga rätten men aldrig hitta tillbaka till den. Se printUrl() i
     app/render.js — den finns bara i utskriften och tar ingen plats på skärmen. */
  .print-url {
    display: block; margin: 0 0 .5cm;
    font-size: 8.5pt; color: #444; word-break: break-all;
  }

  .hero-credit { margin: .2cm 0 .5cm; padding: 0; font-size: 8pt; color: #444; }
  .lede {
    margin: 0 0 .5cm; padding: 0; max-width: none;
    font-size: 12pt; line-height: 1.4;
  }

  /* ---- receptet självt */

  /* En spalt. Två hade sparat papper, men webbläsarnas sidbrytning i rutnät är
     opålitlig och ett recept som delar en instruktion mitt itu är sämre än ett
     som tar en halv sida till. */
  .recipe-cols {
    display: block; max-width: none;
    padding: 0; margin: 0;
  }
  .recipe-cols h2 { font-size: 13pt; margin: 0 0 .2cm; }

  .ingredients {
    box-shadow: none; background: none;
    border: 1pt solid #000; border-radius: 0;
    padding: .4cm .5cm; margin-bottom: .6cm;
    break-inside: avoid;
  }
  /* Rutorna står kvar med flit: på pappret är listan en inköpslista, och en
     ruta att kryssa i är det enda av skärmens interaktion som överlever. */
  .ing label { padding: .12cm .05cm; font-weight: 400; }
  .ing label::before {
    width: 3.4mm; height: 3.4mm; margin-top: 1mm;
    border: .6pt solid #000; border-radius: .5mm; background: #fff;
  }
  .ing { border-bottom: .3pt dashed #999; break-inside: avoid; }

  .steps { padding: 0; }
  .step { break-inside: avoid; padding: .25cm 0; border-bottom: .3pt dashed #999; }
  .step p { font-size: 11pt; line-height: 1.45; }
  /* Rondellen ritas med kant i stället för fylld bakgrund — se blocket överst. */
  .step-n {
    width: 7mm; height: 7mm; background: none; color: #000;
    border: .8pt solid #000; font-size: 11pt;
  }

  /* ---- bilder */

  .step-figure { break-inside: avoid; margin: .3cm 0; }
  .step-figure img { max-height: 5cm; width: auto; box-shadow: none; border-radius: 0; }
  .step-figure figcaption { font-size: 8.5pt; color: #444; }
  /* Bilderna sist är färdiga rätter och upprepar hjälten — de kostar en sida
     var och tillför inget vid spisen. */
  .recipe-gallery { display: none; }

  /* ---- artiklar */

  .prose, .page { max-width: none; padding: 0; }
  .prose p, .prose li { orphans: 2; widows: 2; }
  .prose h2, .prose h3 { break-after: avoid; font-size: 13pt; }
  .prose img { break-inside: avoid; max-height: 8cm; width: auto; box-shadow: none; border-radius: 0; }
  .prose blockquote { border-left: 1.5pt solid #000; color: #000; font-size: 11pt; }
  .prose a { text-decoration: underline; }
  .page-cols { display: block; }
  .page-aside { position: static; }
  .page-aside-inner { position: static; }
  .colophon { border: .5pt solid #000; border-left: 2pt solid #000; break-inside: avoid; }

  /* Källistan är det enda stället där adressen SKRIVS UT i klartext, och det är
     med avsikt. En källhänvisning utan adress går inte att kontrollera, och att
     den går att kontrollera är hela skälet till att listan finns (se sourceList()
     i app/render.js). Samma sak i löptexten hade gjort varje stycke oläsligt. */
  .sources { max-width: none; padding: .4cm 0 0; break-inside: avoid; }
  .sources h2 { border-top: .5pt solid #000; color: #000; }
  .sources a { color: #000; }
  .sources a::after {
    content: " — " attr(href);
    font-size: 8pt; color: #444; word-break: break-all;
  }

  /* ---- listningar
     Ingen skriver ut en kategorisida med flit, men den ska inte komma ut som 24
     svarta rutor om någon gör det: bildväggens foton ligger på `z-index: -2`
     bakom en gradient som skrivaren tar bort. Väggen blir därför en textlista. */
  .wall { display: block; border: 0; background: none; }
  .tile { aspect-ratio: auto; background: none; break-inside: avoid; }
  .tile-img, .tile-link::before, .tile-link::after, .img-fallback { display: none; }
  .tile-link { position: static; padding: .15cm 0; border-bottom: .3pt solid #999; }
  .tile-title { color: #000; font-size: 12pt; text-shadow: none; }
  .tile-note { color: #444; }
  .hero-media, .hero { display: none; }
}

/* ------------------------------------------------------------ tidningssida */

/**
 * Kategorisidan för det som är text — nyheter, humor — byggd som en tidnings
 * förstasida: en etta överst, därunder rader av allt mindre artiklar och sist
 * en spalt notiser.
 *
 * Bildväggen är byggd för recept: kvadrater, foto över hela ytan, titeln
 * ovanpå. Man väljer med ögonen och behöver inget mer. En artikel väljer man
 * med rubriken och ingressen, och en tidning visar dessutom med FORMATET vad
 * som är viktigast. Storlekarna här är därför en trappa och inte ett upprepat
 * mönster: se magazine() i app/render.js.
 *
 * TRE SAKER SKILJER DEN TRYCKTA SIDAN FRÅN KORTRUTNÄTET, och alla tre finns
 * här för att den förra versionen saknade dem och därför läste sig som en
 * blogg hur väl den än var proportionerad:
 *
 * 1. Rutnätet ritas med LINJER, inte med luft. Ett kort som svävar i en
 *    mellanrumsyta är ett kort; en spalt med en hårfin linje i rännan bredvid
 *    sig är en spalt. Linjen ritas mitt i rännan av spalten till höger om den —
 *    se .mag-row för varför den inte får vara en `border-left` på cellen.
 *    Raderna är egna behållare (.mag-row) för att `+ .mag-card` då aldrig kan
 *    sätta en linje vid en radbörjan; det gick inte att göra säkert när allt låg
 *    i ett sexspaltigt rutnät och cellerna spände olika brett.
 * 2. Fotona är RÄTA. Rundade hörn är webbens kort, inte tryckets bilder. Av
 *    samma skäl finns ingen zoom vid hovring: en tidning rör sig inte.
 * 3. Ingen etikett och ingen knapp. Se magLead() i app/render.js.
 *
 * Typografin är tidningens: rubriker i Fraunces tätt satta, fet ingång på
 * ingressen, hårfina linjer i stället för kort med skuggor.
 */

/* Vinjetten står i huvudet (.brand-section), inte här: sidan börjar direkt med
   ettan. Luften ovanför den kommer från .section — mindre än den var, med flit.

   `--rule` är HALVA rännan mellan två spalter, och den bor här för att både
   raderna och notisspalten mäter sig mot den — se .mag-row. Den behöver ingen
   brytpunkt: under 620 px är raderna enspaltiga och under 900 px är notiserna
   det, så en ränna utan grannar att skilja åt kostar ingenting. */
.section.paper {
  --rule: clamp(1rem, 2.2vw, 1.75rem);
  max-width: 74rem;
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
}

/* ------- gemensamt för etta, kort och notiser */

.mag-lead a, .mag-title a, .mag-note-title a { color: var(--head); text-decoration: none; }
.mag-lead a:hover, .mag-title a:hover, .mag-note-title a:hover { color: var(--orange); }
/* Hela ytan blir klickbar härifrån, så bilden slipper vara en andra länk till
   samma artikel — en skärmläsare hade annars läst upp den två gånger. */
.mag-lead-title a::after,
.mag-title a::after,
.mag-note-title a::after { content: ""; position: absolute; inset: 0; }

.mag-img, .mag-lead-img, .mag-note-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}

/* Ingången i fet, tidningens gamla knep. Se deck() i app/render.js. */
.mag-lede { color: var(--head); font-weight: 800; }

/* ------- ettan */

.mag-lead {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1rem, 2.5vw, 1.8rem);
  padding-bottom: clamp(1.4rem, 3vw, 2.2rem);
  border-bottom: 3px solid var(--ink);
}
/*
 * `minmax(0, …)` och inte bara `1.5fr 1fr`: ett fr-spår är i själva verket
 * `minmax(auto, 1fr)` och kan aldrig bli smalare än sitt min-content. Textspaltens
 * min-content är det LÄNGSTA ORDET i rubriken, och svenskan har gott om
 * "Jämställdhetsmyndigheten" — 763 px satt i 3,5 rem. Den lade beslag på 70 % av
 * raden och tryckte ihop fotot till 30 % i stället för utlovade 61 %, olika
 * mycket för varje artikel beroende på dess längsta ord. Mätt på /humor/.
 */
@media (min-width: 820px) {
  .mag-lead { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); align-items: center; }
}

.mag-lead-media {
  position: relative; overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--green-deep);
}

/*
 * Grad och spaltbredd är satta MOT VARANDRA så att avstavningen blir
 * skyddsnätet och inte formgivningen. Uppmätt i Fraunges vid 2,6 rem: det
 * längsta ordet någon etta har haft, "Jämställdhetsmyndigheten", är 467 px och
 * "kulturdepartementet" 364 px. Textspalten är 474 px vid 1,3fr — båda ryms
 * alltså hela, och det är därför spalten inte fick bli smalare.
 *
 * `text-wrap: pretty` och inte `balance`: balance jämnar ut radlängderna, och
 * när en rubrik ändå måste avstavas en gång betalar den utjämningen genom att
 * avstava EN GÅNG TILL. Det var så "kulturdepartementet" bröts mitt i ordet
 * trots att det fick plats på en rad.
 *
 * `hyphens` behövs ändå: mellan 820 och ~1200 px krymper spalten fortare än
 * graden, och utan avstavning spräcker ett långt sammansatt svenskt ord spalten
 * med overflow i stället. Sidan är `lang="sv"`, så brytningen följer svenska
 * ordled; `overflow-wrap` är golvet för den vars webbläsare saknar ordlistan.
 */
.mag-lead-title {
  font-family: var(--display);
  font-variation-settings: 'SOFT' 40, 'WONK' 1, 'opsz' 144;
  font-size: clamp(1.8rem, 3.6vw, 2.6rem);
  line-height: 1.03;
  letter-spacing: -.025em;
  margin: 0 0 .7rem;
  text-wrap: pretty;
  hyphens: auto;
  overflow-wrap: break-word;
}
.mag-lead-intro {
  margin: 0;
  font-size: clamp(1rem, 1.5vw, 1.12rem);
  line-height: 1.5;
  color: var(--muted);
  text-wrap: pretty;
}

/* ------- raderna */

/*
 * Rännan är en RIKTIG `column-gap` och hårlinjen ritas mitt i den med ett
 * pseudoelement, i stället för att ligga som `border-left` på cellen med luften
 * betald ur cellens padding.
 *
 * Skillnaden är inte kosmetisk. Med padding-varianten måste ytterkanterna
 * nollas för att spalterna ska gå jäms med ettan — `:first-child` tappar sin
 * vänsterpadding, `:last-child` sin högra — och då blir MITTENCELLEN i en
 * trerad en ränna smalare än sina grannar. En smalare cell ger en lägre
 * `aspect-ratio`-ruta, alltså ett kortare foto, alltså en rubrik som börjar
 * högre upp än de andra två. Det syntes direkt på /humor/.
 *
 * Med en äkta ränna är alla spår exakt lika breda, ytterkanterna ligger kvar
 * mot ettans kanter, och linjen hamnar mitt emellan spalterna i stället för
 * tätt intill texten. Att den ritas som `::before` och inte som `border-left`
 * är också det som låter den gå hela radens höjd: cellen sträcks av rutnätet,
 * så `top: 0; bottom: 0` möter den vågräta linjen ovanför.
 */
.mag-row {
  display: grid; grid-template-columns: 1fr;
  row-gap: clamp(1.5rem, 3vw, 2rem);
  column-gap: calc(var(--rule) * 2);
}
.mag-row + .mag-row,
.mag-row + .mag-notes { border-top: 1px solid var(--line); }

/* Linjen mitt i rännan, ritad av spalten till höger om den. Den är avstängd
   som grundläge och tänds först vid den brytpunkt där spalten faktiskt HAR en
   granne till vänster — enspaltigt vore den ett lodrätt streck ute i marginalen.
   Att den är absolut positionerad är också det som gör att den inte blir ett
   eget rutnäts- eller flexbarn i cellen den ritas av. */
.mag-card + .mag-card::before,
.mag-note:nth-child(2n)::before {
  content: ""; display: none;
  position: absolute; top: 0; bottom: 0; left: calc(var(--rule) * -1);
  border-left: 1px solid var(--line);
}

/* `minmax(0, 1fr)` av samma skäl som i ettan: spåren ska vara lika breda även
   när en rubrik innehåller ett ord som är bredare än sitt spår. Utan det äter
   den cellen av sina grannar och hela poängen med lika breda spalter faller. */
@media (min-width: 620px) {
  .mag-row { row-gap: 0; }
  .mag-row-mid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mag-row-small { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .mag-card + .mag-card::before { display: block; }
}

.mag-card {
  position: relative;
  display: flex; flex-direction: column;
  padding-top: clamp(1.3rem, 2.6vw, 1.9rem);
  padding-bottom: clamp(.4rem, 1vw, .8rem);
}
/* Fyrkantiga foton — se punkt 2 i blocket överst. */
.mag-media {
  position: relative; overflow: hidden;
  margin-bottom: .8rem;
  background: var(--green-deep);
}
.mag-mid .mag-media { aspect-ratio: 3 / 2; }
.mag-small .mag-media { aspect-ratio: 4 / 3; }
.mag-wide .mag-media { aspect-ratio: 21 / 9; }

.mag-title {
  font-family: var(--display);
  font-variation-settings: 'SOFT' 50, 'WONK' 1, 'opsz' 60;
  line-height: 1.08;
  letter-spacing: -.015em;
  margin: 0 0 .45rem;
  text-wrap: balance;
  hyphens: auto;
  overflow-wrap: break-word;
}
.mag-mid .mag-title { font-size: clamp(1.3rem, 2.7vw, 1.85rem); }
.mag-small .mag-title { font-size: clamp(1.05rem, 1.9vw, 1.25rem); }
.mag-wide .mag-title { font-size: clamp(1.5rem, 3.2vw, 2.2rem); }

/*
 * Bara tvåorna har ingress. Treorna är foto och rubrik — se magCard().
 *
 * Tre rader är GRUNDVÄRDET, inte facit. Två artiklar bredvid varandra har olika
 * långa rubriker — en bryts på två rader, en på en — och rutnätet sträcker båda
 * cellerna till radens höjd. Cellen med kort rubrik får då ett tomt fält under
 * sin ingress, ungefär en rubrikrad hög, alltså mer än en och en halv
 * ingressrad. `--intro-lines` finns för att det fältet ska kunna fyllas med
 * text i stället för med luft; app.js mäter och höjer talet per cell.
 *
 * Antalet är en variabel och inte ett tal just därför: utan skript står
 * ingressen kvar på sina tre rader, vilket är precis vad den gjorde förut.
 */
.mag-intro {
  --intro-lines: 3;
  margin: 0;
  font-size: .94rem;
  line-height: 1.45;
  color: var(--muted);
  text-wrap: pretty;
  /* Klippt vid en hel rad, aldrig mitt i en: raden ska ha en jämn kant, och en
     avhuggen mening är ärligare än en cell som växer förbi sin granne. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--intro-lines);
  line-clamp: var(--intro-lines);
  overflow: hidden;
}
.mag-wide .mag-intro { --intro-lines: 2; }

/* ------- notiserna */

.mag-notes { padding-top: clamp(1.4rem, 2.8vw, 2rem); }

/* Spaltrubriken sitter på en linje, som en sidfotsvinjett i tryck. */
.mag-notes-head {
  font-family: var(--sans);
  font-size: .72rem; font-weight: 800;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 .3rem;
}

.mag-notes-list {
  display: grid; grid-template-columns: 1fr;
  column-gap: calc(var(--rule) * 2);
}
@media (min-width: 900px) {
  .mag-notes-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mag-note:nth-child(2n)::before { display: block; }
}

.mag-note {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 1rem;
  padding-block: .8rem;
  border-top: 1px solid var(--line);
}
.mag-note-title {
  font-family: var(--display);
  font-variation-settings: 'SOFT' 50, 'WONK' 1, 'opsz' 40;
  font-size: clamp(1rem, 1.6vw, 1.12rem);
  line-height: 1.18;
  letter-spacing: -.01em;
  margin: 0;
  text-wrap: pretty;
}
.mag-note-media {
  position: relative; overflow: hidden;
  width: 74px; height: 74px;
  background: var(--green-deep);
}

@media print {
  .mag-lead, .mag-card, .mag-note { break-inside: avoid; }
  .mag-lead-media, .mag-media, .mag-note-media { display: none; }
  .mag-row, .mag-notes-list { display: block; }
  /* Enspaltigt på papper: rännans linje har inget att skilja åt. */
  .mag-card + .mag-card::before, .mag-note::before { display: none; }
}


/* Bildtexten under hjältebilden.

   Samma spaltbredd och sidopadding som .lede, inte hela den helbredda bildens
   bredd: en rad som börjar vid skärmkanten läses som ett bildspråk i en annons
   i stället för som en bildtext i en tidning. Sans mot ingressens antikva, och
   --muted, så att den går att läsa utan att tävla med den. Färgen följer
   automatiskt med i mörkt läge — --muted är omdefinierad där. */
/* Adressen som bara finns på papper. Den står i sidan i stället för att sättas
   in av ett skript, så att utskriften blir densamma med JavaScript avstängt —
   och göms här i stället för med `hidden` i uppmärkningen, för `hidden` går
   inte att slå på igen i `@media print`. Se printUrl() i app/render.js. */
.print-url { display: none; }

.hero-credit {
  max-width: 44rem;
  margin: clamp(0.75rem, 2vw, 1.1rem) auto 0;
  padding: 0 clamp(1rem, 4vw, 2rem);
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--muted);
  text-wrap: pretty;
}
