/* Gedeelde stijl voor de vier pagina's van de pricewatch.
   Vanilla CSS, geen build-stap: wat hier staat is wat de browser krijgt.

   Elke waarde komt uit assets/tokens.css en staat hier als var(--…). Dat
   bestand wordt ervóór geladen — in de schillen met een tweede <link>, in de
   geprerenderde pagina's door document() in prerender.py. Ontbreekt het, dan
   valt de hele pagina terug op ongestyled: er staat hier geen enkele kleur of
   maat meer die het zonder kan.

   Koel licht thema, geen donkere modus. De site is een daglicht-prijstool en de
   signalering (teal voor navigatie, cactusgroen voor beste prijs en voorraad)
   verliest zijn betekenis als je hem omkeert — vandaar bewust geen
   prefers-color-scheme-blok.

   Geen schaduwen: scheiding met haarlijnen in --border of met --surface-sunken. */

*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--font-body);
  font-size:var(--text-md);line-height:var(--leading-normal);-webkit-font-smoothing:antialiased}
main{max-width:64rem;margin:0 auto;padding:0 var(--space-5) var(--space-8)}
a{color:var(--accent-strong);text-decoration:none}
a:hover{text-decoration:underline}
code{font-family:var(--font-mono);font-size:.9em}

/* --- menubalk --- */
.topbar{display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap;
  padding:var(--space-5) 0 var(--space-6);
  border-bottom:var(--border-width) solid var(--border);margin-bottom:var(--space-6)}
.sitemark{display:flex;align-items:center;gap:var(--space-2);flex:none;color:var(--fg);
  font-family:var(--font-display);font-weight:var(--weight-bold);
  letter-spacing:-.035em;font-size:var(--text-md);text-transform:lowercase}
.sitemark:hover{text-decoration:none}
.sitemark svg{width:24px;height:24px;display:block;color:var(--accent);flex:none}
.sitemark em{font-style:normal;color:var(--accent)}
.crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);
  font-size:var(--text-sm);color:var(--fg-muted);min-width:0}
.crumbs .here{color:var(--fg)}
/* Twee keuzes rechtsboven en niet één: de taal bepaalt de woorden, het
   bezorgland bepaalt wélke winkels je ziet en dus welke prijzen. Ze staan naast
   elkaar met een streep ertussen, want "NL EN DE NL DE" op één rij leest als
   één lijst waarin je er precies één aanklikt — en dan is de tweede keuze
   onvindbaar. De actieve landknop is bovendien teal en de actieve taalknop
   zwart: dat is het tweede signaal dat het twee assen zijn en geen twee helften
   van dezelfde. */
.chooser{margin-left:auto;display:flex;align-items:center;gap:var(--space-2);flex:none}
.langs,.landen{display:flex;gap:var(--space-1);flex:none}
.landen{padding-left:var(--space-2);
  border-left:var(--border-width) solid var(--border)}
.lang,.land{font-family:var(--font-mono);font-size:var(--text-xs);
  letter-spacing:var(--tracking-wide);padding:5px 9px;
  border-radius:var(--radius-sm);color:var(--fg-muted)}
.lang{border:var(--border-width) solid transparent}
.lang:hover{color:var(--fg);text-decoration:none;border-color:var(--border)}
.lang.here,.lang.here:hover{background:var(--fg);border-color:var(--fg);
  color:var(--neutral-0);text-decoration:none}
/* De landknoppen dragen hun rand altijd: de taalkeuze is er op elke site en
   wordt herkend, een bezorgland niet, en die mag dus niet pas bij hover
   verschijnen. --accent-strong en niet --accent: op die lichtere teal haalt
   witte tekst van deze grootte de contrasteis niet. */
.land{border:var(--border-width) solid var(--border)}
.land:hover{color:var(--fg);text-decoration:none;border-color:var(--border-strong)}
.land.here,.land.here:hover{background:var(--accent-strong);
  border-color:var(--accent-strong);color:var(--neutral-0);text-decoration:none}

/* --- titelblok --- */
h1{font-family:var(--font-display);font-size:var(--text-2xl);line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);font-weight:var(--weight-bold);margin:0}
h2{font-family:var(--font-display);font-size:var(--text-lg);font-weight:var(--weight-semibold);
  line-height:var(--leading-snug);margin:var(--space-8) 0 var(--space-4)}
p.brand{font-family:var(--font-mono);font-size:var(--text-xs);
  letter-spacing:var(--tracking-wider);text-transform:uppercase;
  color:var(--fg-muted);margin:0 0 var(--space-2)}
p.brand a{color:var(--fg-muted)}
.sub{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--fg-muted);
  margin:var(--space-3) 0 0;line-height:var(--leading-normal)}
.lead{font-size:var(--text-md);color:var(--fg-muted);line-height:var(--leading-normal);
  max-width:46rem;margin:var(--space-4) 0 0}

/* --- tellers --- */
/* De drie getallen onder de titel op de homepage: pedalen, merken, webshops.
   Ze staan naast elkaar en niet onder elkaar, ook op een telefoon: drie korte
   getallen passen op één regel, en onder elkaar duwen ze het zoekveld net zo
   ver naar beneden als de metaregel die hier stond.

   Daarom `nowrap` en geen `wrap`: op 390px braken ze anders af na "33 merken",
   en dan staat er één teller op een tweede regel. De tussenruimte krimpt mee
   (`clamp`) in plaats van dat de rij omvalt. */
.stats{list-style:none;padding:0;margin:var(--space-5) 0 0;
  display:flex;flex-wrap:nowrap;justify-content:center;
  gap:clamp(var(--space-3),4vw,var(--space-6))}
.stats li{display:flex;align-items:baseline;gap:var(--space-2);white-space:nowrap}
.stat-n{font-family:var(--font-display);font-size:var(--text-xl);
  font-weight:var(--weight-bold);letter-spacing:var(--tracking-tight);
  font-variant-numeric:tabular-nums;color:var(--fg)}
.stat-label{font-size:var(--text-sm);color:var(--fg-muted)}

/* --- melding --- */
.notice{margin:var(--space-5) 0 0;padding:var(--space-4);background:var(--accent-tint);
  border:var(--border-width) solid color-mix(in oklab,var(--accent) 22%,transparent);
  border-radius:var(--radius-md);font-size:var(--text-sm);
  line-height:var(--leading-normal);color:var(--fg)}
.notice strong{font-weight:var(--weight-semibold)}

/* --- zoekveld --- */
.search{margin:var(--space-6) 0 0}
.search input{width:100%;font-family:var(--font-body);font-size:var(--text-md);
  color:var(--fg);background:var(--surface);
  border:var(--border-width) solid var(--border-strong);border-radius:var(--radius-md);
  height:52px;padding:0 var(--space-4);outline:none}
.search input::placeholder{color:var(--neutral-300)}
.search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-tint)}
.hint{font-size:var(--text-xs);color:var(--fg-muted);margin:var(--space-2) 0 0}

/* --- de gecentreerde kop --- */
/* Op de homepage titel, tellers en zoekveld; op de categoriepagina het merk, de
   titel en de inleiding. In beide gevallen is dit de aankondiging van de pagina
   en begint wat eronder komt weer links.

   Het zoekveld loopt niet over de volle breedte mee — een invoerveld van 64rem
   naast een titel van tien tekens leest als een formulier en niet als een
   zoekbalk. De inleiding houdt haar leesbreedte van 46rem maar staat wel
   gecentreerd in de kolom; zonder de auto-marges hangt ze links. De melding
   blijft links uitgelijnd: dat is een zin en geen kop. */
.hero{text-align:center;margin-bottom:var(--space-8)}
.hero .search{max-width:34rem;margin-left:auto;margin-right:auto}
.hero .lead{margin-left:auto;margin-right:auto}
.hero .notice{text-align:left}
/* Het merklogo boven de titel op de merkpagina. Vaste hoogte en geen vaste
   breedte: de logo's zijn tot op de witruimte bijgesneden (zie to_webp() in
   fetch_logos.py) maar hun verhouding verschilt van een breed woordmerk tot een
   vierkant beeldmerk, en op één hoogte zetten is de enige maat die ze naast
   elkaar even groot laat lijken. De maximumbreedte vangt het uiterste geval af.
   `object-fit` doet hier niets zolang er geen tweede maat opgelegd wordt, maar
   staat er als vangnet voor een bron die ooit iets anders aanlevert. */
.brand-logo{height:36px;max-width:14rem;object-fit:contain;display:block;
  margin:0 auto var(--space-4)}

/* --- prijstabellen --- */
/* Eén blok per ingang: naam, tabel met vier regels, link eronder. Op de
   homepage een blok per hoofdcategorie, op de categoriepagina een blok per
   subcategorie. Naast elkaar zodra het past — dertien tabellen onder elkaar is
   anders een pagina van vijf schermen, en de tabellen zijn juist bedoeld om te
   scannen. */
/* `min(20rem,100%)` en niet kaal `20rem`: op een scherm smaller dan 20rem houdt
   auto-fill die 20rem alsnog aan, en dan steekt het raster buiten de pagina met
   een horizontale schuifbalk als gevolg. */
.browse{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(20rem,100%),1fr));
  gap:var(--space-6) var(--space-5)}

/* Het dalersblok op de homepage staat als enige buiten het raster van de
   categorieën — één brede tabel in plaats van een kolom — en heeft daarom zijn
   eigen ruimte eronder nodig. Zonder deze regel staat de link "alle
   prijsdalers…" naast de eerste categoriekop in plaats van onder zijn eigen
   tabel. Dezelfde maat als de rijen van het raster eronder.
   Geen `display` in deze regel: dat zou het `hidden`-attribuut overrulen, en
   dan staat er een lege sectie op een dag zonder dalers — precies de val die
   verderop bij `.browse[hidden]` beschreven staat. */
#drops-section{margin-bottom:var(--space-6)}

.cat{min-width:0}
/* De kopregel is de kolomkop van de tabel: naam links, "Vanaf" rechts boven de
   prijzen. Hij staat bewust búiten `.table-wrap` — daarbinnen zou hij in het
   omkaderde vlak zitten, en hij hoort op de paginaachtergrond en zonder rand.
   De onzichtbare kolomkoppen staan wél in de tabel, voor een schermlezer. */
.cat-head{display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--space-4);margin:0 0 var(--space-2)}
.cat-head h2{margin:0;min-width:0}
.cat-from{font-family:var(--font-mono);font-size:var(--text-xs);
  letter-spacing:var(--tracking-wide);text-transform:uppercase;
  color:var(--fg-muted);flex:none}
/* Rechts uitgelijnd met de rechterrand van de tabel, net als "Vanaf" erboven. */
.more{margin:var(--space-2) 0 0;font-size:var(--text-sm);text-align:right}

/* --- merkenrij --- */
.brands{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:var(--space-2)}
.brands a{display:inline-flex;align-items:center;gap:var(--space-2);height:36px;
  padding:0 var(--space-3) 0 var(--space-4);
  border:var(--border-width) solid var(--border);border-radius:var(--radius-round);
  background:var(--surface);font-size:var(--text-sm);color:var(--fg)}
.brands a:hover{border-color:var(--border-strong);text-decoration:none}
.tally{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--fg-muted);
  background:var(--surface-sunken);border-radius:var(--radius-round);padding:2px 7px}

/* De losse modellen op de merkpagina volgen op het blokkenraster erboven, en
   hun kop zit in een `.cat-head` — die zet de `margin-top` van de h2 op nul, dus
   zonder deze regel plakt de lijst tegen het laatste prijsblok aan. Dezelfde
   maat als de ruimte die een gewone h2 zelf meebrengt. */
#loose-section{margin-top:var(--space-8)}

/* --- modellijst --- */
.results{list-style:none;padding:0;margin:0;border:var(--border-width) solid var(--border);
  border-radius:var(--radius-md);background:var(--surface);overflow:hidden}
.results li+li{border-top:var(--border-width) solid var(--border)}
.results li>a{display:grid;grid-template-columns:40px 1fr auto;align-items:center;
  gap:var(--space-4);padding:var(--space-3) var(--space-4);color:inherit}
.results li>a:hover{background:var(--surface-sunken);text-decoration:none}
.hit-name{font-weight:var(--weight-semibold);font-size:var(--text-sm);display:block}
.hit-path{font-size:var(--text-xs);color:var(--fg-muted);display:block;margin-top:2px}
.hit-price{font-family:var(--font-mono);font-size:var(--text-sm);
  font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.results .none{padding:var(--space-4);display:block}

/* --- thumbnail --- */
.thumb{width:40px;height:40px;object-fit:contain;background:var(--surface-sunken);
  border-radius:var(--radius-sm);display:block}
.thumb-empty{border:1px dashed var(--border-strong);background:transparent}

/* --- tabellen --- */
.table-wrap{border:var(--border-width) solid var(--border);border-radius:var(--radius-md);
  background:var(--surface);overflow:hidden}
/* De tabel is het eerste blok van #content en had zelf geen ruimte erboven: die
   kwam van de melding die ertussen stond. Nu die er niet meer is (en op een dag
   zonder stille winkels stond ze er toch al niet) plakte de tabel tegen de
   beschrijving aan. Alleen binnen #content, want de prijsblokken op de homepage
   hebben hun eigen kop erboven.

   Alleen als eerste kind: staat er een kop "Alle modellen" boven — dat gebeurt
   op een categorie met subcategorieën — dan komt de ruimte van die kop. */
#content>.table-wrap:first-child{margin-top:var(--space-6)}
table{width:100%;border-collapse:collapse;font-size:var(--text-sm)}
th{text-align:left;font-family:var(--font-mono);font-size:var(--text-xs);
  font-weight:var(--weight-regular);letter-spacing:var(--tracking-wide);
  text-transform:uppercase;color:var(--fg-muted);padding:var(--space-3) var(--space-4);
  border-bottom:var(--border-width) solid var(--border);white-space:nowrap}
td{padding:var(--space-3) var(--space-4);
  border-top:var(--border-width) solid var(--border);vertical-align:middle}
tbody tr:first-child td{border-top:0}
tbody tr:hover{background:var(--surface-sunken)}
td.rank,th.rank{font-family:var(--font-mono);color:var(--fg-muted);
  font-variant-numeric:tabular-nums;width:2.5rem;text-align:right;padding-right:0}
.thumb-cell{width:40px;padding-right:0}
td.price,th.price{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  text-align:right;white-space:nowrap}
td.price{font-weight:var(--weight-semibold)}
.oos{font-family:var(--font-body);font-size:var(--text-xs);
  font-weight:var(--weight-regular);color:var(--fg-muted);margin-top:2px}
.none{color:var(--fg-muted);font-style:italic;font-weight:var(--weight-regular)}

/* --- dalingskolom --- */
/* De laatste kolom van dalers.html en van het dalersblok op de homepage. Zelfde
   opmaak als een prijs — mono, tabulaire cijfers, rechts uitgelijnd — zodat de
   twee getalkolommen naast elkaar op dezelfde manier lezen en de percentages
   onder elkaar uitkomen. De kleur is die van de beste prijs in de
   aanbiederstabel: een daling is nieuws in het voordeel van de lezer, en het is
   het enige wat deze tabel van de categorietabel onderscheidt. */
td.drop,th.drop{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  text-align:right;white-space:nowrap}
td.drop{font-weight:var(--weight-semibold);color:var(--positive)}

/* --- aanbiederstabel --- */
/* De beste-prijsregel krijgt .best, regels zonder voorraad .dim. Beide worden
   in renderOffers() gezet (assets/product.js) en in render_product()
   (prerender.py); de volgorde zelf komt ongewijzigd uit offersOf(). */
.offers tr.best td,.offers tr.best:hover td{background:var(--positive-tint)}
.offers tr.best td:first-child{box-shadow:inset 3px 0 0 var(--positive)}
.offers tr.dim td{color:var(--fg-muted)}
.badge{display:inline-block;font-family:var(--font-mono);font-size:var(--text-xs);
  letter-spacing:var(--tracking-wide);text-transform:uppercase;padding:2px 7px;
  border-radius:var(--radius-sm);background:var(--positive);color:#fff;
  margin-left:var(--space-2);white-space:nowrap}
.stock-yes{color:var(--positive)}
.stock-no{color:var(--fg-muted)}

/* --- productintro --- */
.intro{display:grid;grid-template-columns:240px 1fr;gap:var(--space-6);
  align-items:start;margin-top:var(--space-6)}
.shot{margin:0}
.shot img{width:100%;height:auto;display:block;background:var(--surface);
  border:var(--border-width) solid var(--border);border-radius:var(--radius-md)}
.shot figcaption{font-size:var(--text-xs);color:var(--neutral-300);margin-top:var(--space-2)}
.shot figcaption a{color:var(--neutral-300)}
.desc{margin:0;font-size:var(--text-md);line-height:var(--leading-normal);color:var(--fg)}

/* --- prijsverloop --- */
#history-section .chart-wrap,.chart-wrap{border:var(--border-width) solid var(--border);
  border-radius:var(--radius-md);background:var(--surface);padding:var(--space-5)}
.chart{width:100%;height:auto;display:block;overflow:visible}
.chart .grid{stroke:var(--border)}
.chart .area{fill:var(--accent-tint)}
.chart .line{stroke:var(--accent);stroke-width:2;fill:none;
  stroke-linejoin:round;stroke-linecap:round}
.chart .dot{fill:var(--surface);stroke:var(--accent);stroke-width:1.5}
.chart .cursor{stroke:var(--border-strong);stroke-dasharray:3 3}
.chart .focus{fill:none;stroke:var(--accent);stroke-width:2}
.chart .axis-label{font-family:var(--font-mono);font-size:11px;fill:var(--fg-muted)}
.chart-tip{font-family:var(--font-mono);font-size:var(--text-xs);background:var(--fg);
  color:var(--neutral-0);padding:4px 8px;border-radius:var(--radius-sm);white-space:nowrap}
.chart-caption{font-size:var(--text-sm);color:var(--fg);margin:var(--space-4) 0 0}
.chart-note{font-size:var(--text-xs);color:var(--fg-muted);margin:var(--space-2) 0 0;
  line-height:var(--leading-normal)}

/* --- voettekst --- */
footer{margin-top:var(--space-8);padding-top:var(--space-5);
  border-top:var(--border-width) solid var(--border);
  font-size:var(--text-xs);color:var(--fg-muted);line-height:var(--leading-normal)}

/* De sitevoettekst met de privacylink. Staat buiten <main> en dus buiten de
   inhoudsbreedte-regels daar; vandaar dezelfde marges als de pagina zelf. Geen
   rand erboven: de paginavoettekst heeft er al een, en twee lijnen onder elkaar
   lezen als een fout. */
.site-links{margin:var(--space-6) auto;padding:0 var(--space-5);
  max-width:64rem;border-top:none;font-size:var(--text-xs)}

.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap}

@media(max-width:640px){
  .intro{grid-template-columns:1fr}

  /* De tellerrij blijft één regel, ook op een smal toestel: op 320px stak ze
     er anders 27px buiten en kreeg de héle pagina een horizontale schuifbalk.
     Een maat kleiner en een krappere tussenruimte houdt "520 pedalen · 33
     merken · 14 webshops" binnen de rand. */
  .stats{gap:clamp(var(--space-1),2vw,var(--space-5))}
  .stat-n{font-size:var(--text-lg)}
  .stat-label{font-size:var(--text-xs)}
  /* Gecentreerd: de beschrijving staat op deze breedte onder de foto in plaats
     van ernaast, en links uitgelijnd tegen een volle breedte oogt dat scheef. */
  .shot{max-width:240px;margin-inline:auto}
  h1{font-size:var(--text-xl)}

  /* De aanbiederstabel als blokjes in plaats van als vier kolommen. Vier
     kolommen naast elkaar passen niet op een telefoon: op een iPhone (390px)
     werd de tabel 624px breed in een vak van 340px, en `.table-wrap` snijdt af
     — precies de prijs, de voorraad en de link vielen weg, terwijl de
     winkelnaam bleef staan. De pagina zag er dus niet kapot uit maar leeg, en
     dat is hetzelfde faalgeval als regel 10: een gat dat leest alsof er niets
     te koop is.

     Elke rij wordt hier een raster van twee kolommen, in bronvolgorde gevuld:

         Thomann  BESTE PRIJS          € 115,00
         op voorraad                naar winkel

     Alles zit in de CSS en niets in de opbouw, zodat renderOffers() in
     product.js en render_product() in prerender.py dezelfde HTML blijven
     leveren.

     Bijkomstigheid van `display:block` op tabelonderdelen: de browser haalt de
     tabelrol uit de toegankelijkheidsboom, dus een schermlezer krijgt hier geen
     kolomkoppen. Dat weegt op tegen de kolommen die er visueel helemaal niet
     meer zijn, en de leesvolgorde blijft wel kloppen: winkel, prijs, voorraad,
     link. */
  .offers thead{display:none}
  .offers,.offers tbody,.offers tr,.offers td{display:block}
  .offers tr{display:grid;grid-template-columns:minmax(0,1fr) auto;
    column-gap:var(--space-4);row-gap:var(--space-1);align-items:baseline;
    padding:var(--space-3) var(--space-4);
    border-top:var(--border-width) solid var(--border)}
  .offers tbody tr:first-child{border-top:0}
  .offers td{padding:0;border-top:0}
  .offers td:nth-child(1),.offers td:nth-child(3){grid-column:1}
  .offers td:nth-child(2),.offers td:nth-child(4){grid-column:2;text-align:right}
  .offers td:nth-child(3),.offers td:nth-child(4){font-size:var(--text-xs)}

  /* De markering van de beste prijs zat op de cellen; als blokje in een raster
     dekken die niet meer de hele regel, dus hij verhuist naar de rij zelf. */
  .offers tr.best,.offers tr.best:hover{background:var(--positive-tint);
    box-shadow:inset 3px 0 0 var(--positive)}
  .offers tr.best td,.offers tr.best:hover td{background:none}
  .offers tr.best td:first-child{box-shadow:none}

  /* Een winkel zonder prijs draagt geen bedrag maar een zin ("pagina niet op te
     halen"). Rechts uitgelijnd in een halve kolom wordt dat een smalle
     woordslinger, dus die krijgt de volle breedte onder de winkelnaam — en de
     voorraadcel ernaast is dan toch niets dan een streepje. */
  .offers td.price:has(.none){grid-column:1/-1;text-align:left}
  .offers tr:has(td.price .none) td:nth-child(3){display:none}

  /* De dalerstabel heeft vijf kolommen en dat zijn er op een telefoon twee te
     veel: naast de foto stonden een bedrag én een percentage, en de modelnaam
     hield er 120px van over — "Electro-Harmonix LPB-1 Linear Power Booster"
     werd vijf regels hoog naast één regel cijfers.

     Dus dezelfde ingreep als bij de aanbiederstabel hierboven: elke rij wordt
     een raster, de naam krijgt de volle breedte en de twee getallen komen
     eronder te staan.

         [foto]  Electro-Harmonix LPB-1 Linear Power Booster
                 € 37,95                              −19,3%

     Het rangnummer valt weg: dat zegt hetzelfde als de volgorde waarin de
     regels staan. Net als daar haalt `display:block` de tabelrol uit de
     toegankelijkheidsboom en verdwijnen de kolomkoppen voor een schermlezer;
     de leesvolgorde blijft kloppen — model, prijs, daling. */
  .drops thead{display:none}
  .drops,.drops tbody,.drops tr,.drops td{display:block}
  .drops tbody tr{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
    column-gap:var(--space-4);row-gap:var(--space-1);align-items:baseline;
    padding:var(--space-3) var(--space-4);
    border-top:var(--border-width) solid var(--border)}
  .drops tbody tr:first-child{border-top:0}
  .drops td{padding:0;border-top:0}
  .drops td.rank{display:none}
  .drops td.thumb-cell{grid-column:1;grid-row:1/3;align-self:center;width:auto}
  .drops td.name{grid-column:2/4;grid-row:1}
  .drops td.price{grid-column:2;grid-row:2;text-align:left}
  .drops td.drop{grid-column:3;grid-row:2}
  /* De regel die zegt dat er niets gedaald is heeft geen kolommen om in te
     staan: colspan doet in een raster niets. */
  .drops td.none{grid-column:1/-1}
}

/* ------------------------------------------------------------------ gedrag

   Hieronder staat geen opmaak maar werking: regels waar JavaScript of een
   toetsenbordgebruiker op rekent. Ze staan apart zodat ze bij een volgende
   restyle niet per ongeluk met het uiterlijk mee weggegooid worden. */

/* De tooltip van de grafiek wordt in pixels binnen .chart-wrap gepositioneerd
   (zie attachHover() in product.js). Zonder een positioneringscontext valt hij
   terug op de pagina zelf en staat hij ergens linksboven; pointer-events uit,
   want anders vangt hij onder de muis zijn eigen beweging op en knippert hij. */
.chart-wrap{position:relative}
.chart-tip{position:absolute;transform:translate(-50%,-115%);pointer-events:none}

/* De aanwijslijn volgt de vinger; zonder dit scrollt de pagina eronder mee. */
.chart{touch-action:none}

/* `display:grid` uit een auteursregel wint van de `display:none` die de browser
   aan het hidden-attribuut hangt. Een lege blokkenrij is daardoor niet écht
   verborgen — hij is nu nog nul pixels hoog omdat er geen kinderen in zitten,
   maar de eerste `gap` of `padding` erbij zet er ruimte neer waar niets staat.
   Dat geldt sinds 2026-08-23 ook voor #series op de merkpagina, dat hetzelfde
   raster gebruikt. */
.browse[hidden]{display:none}

/* Aanwijslijn en aangewezen punt staan vanaf het begin in de SVG maar pas ná
   het aanwijzen op een zinnige plek; ze staan uit met het hidden-attribuut, en
   de regel [hidden]{display:none} uit de browserstijl geldt alleen voor
   HTML-elementen. Zonder deze regel staat er bij het laden een streepjeslijn
   tegen de linkerrand. */
.chart .cursor[hidden],.chart .focus[hidden]{display:none}

/* Zichtbare focus voor wie met het toetsenbord navigeert. Het zoekveld heeft
   zijn eigen ring (border + accent-tint hierboven) en krijgt er geen tweede
   omheen. */
a:focus-visible,.chart:focus-visible,input:focus-visible{outline:2px solid var(--focus-ring);
  outline-offset:2px}
.search input:focus-visible{outline:none}

/* Het bedrag blijft op één regel, de voorraadnoot eronder niet: die erft de
   nowrap van de prijscel, en dan bepaalt "nergens op voorraad" de kolombreedte
   — op een telefoon ging daar meer breedte heen dan de modelnaam kreeg. */
td.price .oos{white-space:normal}

/* Om dezelfde reden mag de foutzin in een prijscel afbreken. Een winkel zonder
   prijs krijgt daar geen bedrag maar "geen productgegevens op de pagina", en
   met de nowrap van de cel eromheen zet één zo'n regel de hele tabel breder dan
   het scherm. `.table-wrap` snijdt dat af in plaats van te schuiven, dus de
   prijzen van álle andere winkels vielen erdoor weg. */
td.price .none{white-space:normal}

/* Het introblok is twee kolommen mét foto en één zonder. Lang niet elk model
   heeft er een, en dan verbergt renderShot() de figure: zonder deze regel houdt
   de beschrijving de kolom van 240px die voor de foto bedoeld was. */
.intro:has(> .shot[hidden]){grid-template-columns:1fr}
