/* One variable file per subset carries 400, 500 and 600. The files are the ones Google Fonts
   serves (v7), unchanged. Only latin is preloaded: no served text needs latin-ext today, and
   the unicode-range means it is fetched only if a character from it ever appears. */
@font-face{
  font-family:'Schibsted Grotesk';font-style:normal;font-weight:400 600;font-display:optional;
  src:url(fonts/schibsted-grotesk-latin-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:'Schibsted Grotesk';font-style:normal;font-weight:400 600;font-display:optional;
  src:url(fonts/schibsted-grotesk-latin.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;
}
:root{
  /* ground system: grey page, surfaces are ink at low opacity. No grey hexes. */
  --ground:#F0F0F0;
  --raised:#FFFFFF;
  --ink:#1A1A1A;
  /* system-v2 had --dim:#8E8E8E, which measures 2.87:1 on this grey ground and 3.28:1
     on white. It carries .t-tiny, the rail label and the number band labels, including
     the source note, so it was a real failure. Ink at 65 percent is the same principle
     the system states for surfaces and measures 5.12:1 on --ground, 5.40:1 on --raised
     and 4.90:1 on the --card tint. */
  --dim:rgba(26,26,26,.65);
  --card:rgba(26,26,26,.055);
  --card-hover:rgba(26,26,26,.085);
  --hairline:rgba(26,26,26,.14);
  /* hairline at .14 is right for rules between rows, but too faint for the two objects
     that ARE the content: the country outline and the 24 unfilled circles. */
  --hairline-strong:rgba(26,26,26,.34);
  --map-line:rgba(26,26,26,.55);
  /* round 20: the logo's palette. The dark surfaces are a deeper shade of the logo navy
     (#1d3e82): white on it measures 13.52:1 against the logo navy's 10.18:1, and the white
     logo gets more room. The header is white so the colour mark sits on the ground it was
     drawn for; on navy its own navy petals would measure 1.33:1. */
  --navy:#152c5e;
  --dark:var(--navy);

  /* the logo's teal, from the cross at its centre. The fill value is the logo's own and
     carries graphics (the map circle, link underlines): 4.17:1 on --ground, over the 3:1 a
     graphic needs. Text, figures and the focus ring use a deeper teal: 5.42:1 on --ground,
     6.18:1 on white, 4.86:1 on the --card tint, because the logo teal itself is 4.17:1 on
     --ground, under the 4.5:1 that text needs. */
  --accent:#007d9d;
  --accent-ink:#006a85;
  --accent-wash:rgba(0,125,157,.10);
  /* the logo's red is kept for the one thing the site asks of people: Doneren. White on it
     measures 5.08:1 and on its deep hover fill 8.41:1. Form errors take their own, slightly
     deeper red (5.29:1 on --ground, 6.03:1 on white) so an error never reads as a button. */
  --donate:#dd0b15;
  --donate-deep:#9e0810;
  --error:#c70a13;

  --r-card:15px; --r-btn:10px;
  --card-pad:20px;
  --gap:2px;
  --pad:20px;
  --z-reveal:0; --z-page:2; --z-rail:80; --z-logo:85; --z-nav:90; --z-footfocus:95; --z-menu:110;
  --reveal:0px;
}
@media (min-width:1024px){
  :root{ --r-card:20px; --gap:5px; --pad:30px; --card-pad:50px; --reveal:320px; }
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{
  font-family:'Schibsted Grotesk',system-ui,sans-serif;
  background:var(--ground); color:var(--ink);
  font-size:16px; line-height:1.2; letter-spacing:-.04em;
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent-ink);outline-offset:3px}
/* the teal ring measures 2.19:1 against the navy, under the 3:1 that a focus indicator
   needs, so on the navy surfaces the ring goes white, which measures 13.52:1. The header is
   white now and keeps the teal ring (6.18:1). */
.mmenu :focus-visible,.card.dark :focus-visible,.foot :focus-visible{outline-color:#fff}
/* a section a link has scrolled to takes focus only as a starting point for the next Tab; a ring
   around the whole card would say it is a control, which it is not */
section[tabindex="-1"]:focus-visible{outline:none}
/* on the home page from 1024 up the right end of the nav sits over the photograph, where no
   single colour is safe. A white ring inside a dark halo keeps one of the two edges above
   3:1 whatever pixel it lands on. The halo is legibility, not decoration. */
@media (min-width:1024px){ .hero .nav-right :focus-visible{outline-color:#fff;box-shadow:0 0 0 5px rgba(0,0,0,.6)} }
[hidden]{display:none!important}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
picture{display:contents}
img{display:block;max-width:100%}

/* type scale: weight ceiling 600, line height descends as size grows */
.t-huge{font-size:30px;font-weight:600;line-height:1.2;text-wrap:balance}
.t-large{font-size:30px;font-weight:600;line-height:1.2;text-wrap:balance}
.t-stat{font-size:52px;font-weight:400;line-height:.9}
.t-body{font-size:16px;font-weight:400;line-height:1.5;letter-spacing:-.02em}
.t-nav{font-size:16px;font-weight:500;line-height:1.15;letter-spacing:-.01em}
.t-label{font-size:14px;font-weight:500;line-height:1.2}
.t-tiny{font-size:11px;font-weight:400;line-height:1.15;letter-spacing:-.02em;color:var(--dim)}
@media (min-width:768px){
  .t-huge{font-size:45px}
  .t-stat{font-size:66px}
  .t-body{font-size:20px;line-height:1.4}
  .t-label{font-size:12px}   /* smaller on desktop, deliberate */
  .t-tiny{font-size:12px}
}

/* line masks: each rendered line rises out of its own overflow mask. The padding and
   the equal negative margin cancel in layout, so height is unchanged and CLS stays 0. */
.ln{display:block;overflow:hidden;padding-bottom:.06em;margin-bottom:-.06em}
.li{display:block}

.pill{
  position:relative;isolation:isolate;overflow:hidden;
  display:inline-flex;align-items:center;background:var(--donate);color:#fff;
  font-size:16px;font-weight:600;letter-spacing:-.04em;line-height:1.2;
  padding:15px 28px;border-radius:100vw;cursor:pointer;white-space:nowrap;
  transition:transform .18s ease-out;
}
.pill::after{
  content:'';position:absolute;inset:0;z-index:-1;background:var(--donate-deep);
  transform:scaleX(0);transform-origin:var(--ox,left) center;
  transition:transform .45s cubic-bezier(.32,.72,0,1);
}
.pill:hover::after,.pill:focus-visible::after{transform:scaleX(1)}
.pill:hover{transform:translateY(-1px)}
.pill:active{transform:translateY(-1px) scale(.98)}
/* The underline is what says this is a link, so it has to clear 3:1 as a non text indicator.
   --hairline is ink at 14 percent, which flattens to 1.33:1 on a white surface: round 9 fixed
   exactly this on the dark cards and left the light side alone because no ghost sat on a light
   surface until the Doneren page. Ink at 48 percent measures 3.15:1, and it mirrors the white
   at 48 percent used on dark. */
.ghost{position:relative;border-bottom:1px solid rgba(26,26,26,.48);padding-bottom:2px}
.ghost::after{
  content:'';position:absolute;left:0;bottom:-1px;width:100%;height:1px;background:var(--accent);
  transform:scaleX(0);transform-origin:left center;transition:transform .3s cubic-bezier(.32,.72,0,1);
}
.ghost:hover::after,.ghost:focus-visible::after{transform:scaleX(1)}
/* on a dark card the ghost's underline was --hairline, which is ink at 14 percent and
   measures 1.00:1 against --dark, so the affordance was invisible. White at 48 percent
   measures 4.91:1, and the hover line goes white too, since the teal on navy is 2.84:1. */
.card.dark .ghost{border-color:rgba(255,255,255,.48)}
.card.dark .ghost::after{background:#fff}
.u-grow{position:relative;padding-bottom:2px}
.u-grow::after{
  content:'';position:absolute;left:0;bottom:0;width:100%;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left center;transition:transform .3s cubic-bezier(.32,.72,0,1);
}
.u-grow:hover::after,.u-grow:focus-visible::after{transform:scaleX(1)}

/* nav over the hero. Plain text items stay on the white panel in navy; only the language
   toggle and the pill sit over the photograph, and the pill carries its own ground. */
.nav{
  position:absolute;top:0;left:0;right:0;z-index:var(--z-nav);
  display:flex;align-items:center;gap:24px;padding:20px var(--pad);color:var(--navy);
}
.brand{display:flex;align-items:center;gap:12px;flex-shrink:0}
.brand img{width:38px;height:auto;display:block}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* the small text beside the mark is a scroll ticker: on the home page the name of the
   section you are in, elsewhere the page name. The build writes the first state into the
   markup, so the script's first write changes nothing. */
.nav-ticker{
  font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  line-height:1.25;max-width:170px;display:flex;align-items:center;
  /* a fixed height, not a minimum: the default name wraps to more lines than a section
     name, and letting the box resize moved the text and registered a layout shift */
  height:42px;
}
@media (min-width:901px){ .nav-ticker{height:30px} }
.nav-links{display:flex;gap:20px;margin-left:32px}
.nav-links a{position:relative;opacity:.82}
.nav-links a::after{
  content:'';position:absolute;left:0;bottom:-3px;width:100%;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left center;transition:transform .3s cubic-bezier(.32,.72,0,1);
}
.nav-links a:hover::after,.nav-links a:focus-visible::after{transform:scaleX(1)}
.nav-right{margin-left:auto;display:flex;align-items:center;gap:24px}
.lang{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;letter-spacing:-.01em}
/* the inactive label sits over the photograph. At .62 it computes to about 4.3:1
   against the brightest brick behind it, so the inactive value stays at .78. */
.lang-lbl{opacity:.78;transition:opacity .25s}
html[data-lang="nl"] .lang-lbl[data-lang-lbl="nl"],
html[data-lang="en"] .lang-lbl[data-lang-lbl="en"]{opacity:1}
.lang-switch{
  width:30px;height:15px;border-radius:9999px;border:1px solid var(--hairline-strong);
  position:relative;flex-shrink:0;cursor:pointer;transition:transform .18s ease-out;
}
.lang-switch::before{content:'';position:absolute;inset:-14px -8px}
.lang-switch i{
  position:absolute;top:-1px;left:-1px;width:15px;height:15px;border-radius:9999px;
  background:var(--ink);transition:transform .1s ease-out;
}
html[data-lang="en"] .lang-switch i{transform:translateX(15px)}
.lang-switch:active{transform:scale(.94)}
/* in the white header the switch is navy: the track at 60 percent measures 3.95:1, over
   the 3:1 a control boundary needs. Over the photograph and on navy it needs light strokes. */
.nav .lang-switch{border-color:rgba(21,44,94,.6)}
.nav .lang-switch i{background:var(--navy)}
.mmenu .lang-switch{border-color:rgba(255,255,255,.55)}
.mmenu .lang-switch i{background:#fff}
@media (min-width:1024px){
  .hero .nav .lang{color:#fff}
  .hero .nav .lang-switch{border-color:rgba(255,255,255,.55)}
  .hero .nav .lang-switch i{background:#fff}
  /* Over the hero photograph the white labels met the window's white bars: the worst pixel
     behind them measured 1.04:1. A navy backing that hugs the control fixes that wherever the
     photo is light. Navy at 82 percent over a pure white pixel still gives the active label
     7.77:1 and the dimmed one (78 percent) 5.49:1. It is a pseudo element, so the control keeps
     its size and nothing in the header moves. */
  .hero .nav .lang{position:relative;isolation:isolate}
  .hero .nav .lang::before{content:'';position:absolute;inset:-6px -12px;z-index:-1;border-radius:100vw;background:rgba(21,44,94,.82)}
}
.foot .lang-switch{border-color:rgba(255,255,255,.55)}
.foot .lang-switch i{background:#fff}
.menu-btn{display:none;width:44px;height:44px;align-items:center;justify-content:center;flex-shrink:0;transition:transform .18s ease-out}
.menu-btn:active{transform:scale(.94)}
.menu-btn svg{width:22px;height:12px;display:block}

/* hero: split, panel left, photograph full height right, nothing above it */
.hero{position:relative;display:grid;grid-template-columns:minmax(0,1fr)}
.panel{
  background:var(--raised);color:var(--navy);padding:110px var(--pad) var(--pad);
  display:flex;flex-direction:column;justify-content:flex-end;
}
.panel .t-huge{max-width:16ch}
/* navy at 78 percent on white measures 6.87:1, the eyebrow at 72 percent 5.65:1 */
.panel .t-body{color:rgba(21,44,94,.78);margin-top:20px;max-width:36ch}
.row{margin-top:30px;display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.mt-20{margin-top:20px}
.mt-24{margin-top:24px}
/* the band cancels the card padding on three sides so it meets the card's outer edge,
   and carries the card radius only on the two corners that touch that edge */
/* A card whose media meets its own outer edge carries no padding itself: the padding
   moves to the content wrapper. That way the band spans the full width with no negative
   margin cancelling anything, which is both less fragile and not an overlap. */
.card.bleed{padding:0}
.card.bleed > .two{padding:var(--card-pad) var(--card-pad) 0}
.band-media{
  margin-top:40px;
  border-radius:0 0 var(--r-card) var(--r-card);
  overflow:hidden;
  /* Explicit heights per breakpoint, not a clamp. The clamp this replaces was the reason the
     band still looked unchanged: a clamp of 260px, 30vw and 420px only lets its middle term
     decide between 867px and 1400px of viewport, so every width from 320 to 866 was pinned to
     the 260px floor and everything past 1400 to the 420px ceiling. 375 and 768 both rendered
     at exactly 260px, which is why there was no visible progression. The frame carries the
     floor share now, so height is free and stated outright.
     Deliberately written without the clamp function's own syntax: grepping the served file
     for that syntax is how this change gets verified, and a comment quoting it would make the
     check report a value that is no longer in force. */
  height:340px;
}
@media (min-width:768px){ .band-media{height:400px} }
@media (min-width:1024px){ .band-media{height:480px} }
/* The Geven frame changed in round 14. The previous one was an empty room, and at band
   ratios an empty room is a texture: most of its width carried nothing. This one is a hallway
   with three pieces of structure spread across the frame, and the anchor is derived from where
   they sit rather than chosen by eye. As fractions of the frame: the mirror occupies x .12 to
   .24 and y .12 to .72, the sideboard x .07 to .36 and y .74 to 1, the centre doorway into a
   lit room x .40 to .51 and y .33 to .68, the open door on the right x .80 to .95 and y .14 to
   1, and the window seen through it x .74 to .80 and y .30 to .70.
   The widest band this card draws is 2.83:1, which shows 52.9 percent of a 1.5:1 frame. A
   slice of that depth placed at y .25 to .78 holds the centre doorway whole, the mirror, the
   top of the sideboard, the right door and its window, so the vertical anchor is
   .25 / (1 - .529) = 53 percent, rounded to 52. Horizontally the tightest case is 320px, which
   keeps 61.9 percent of the width; centred that is x .19 to .81, which still holds the left
   furniture, the centre doorway and the right window, so 50 percent across. */
.band-media img{width:100%;height:100%;object-fit:cover;object-position:50% 52%;transition:transform .6s ease-out}
.band-media:hover img{transform:scale(1.02)}
/* The same band inverted, along the top of the card. Only three things swap ends: which
   edge of the content wrapper carries no padding, which two corners take the card radius,
   and which side of the band the 40px gap sits on. Same class, same height, so the two
   bands are one pattern read in two directions rather than two separate devices. */
.card.bleed-top > .two{padding:0 var(--card-pad) var(--card-pad)}
.bleed-top .band-media{margin-top:0;margin-bottom:40px;border-radius:var(--r-card) var(--r-card) 0 0}
/* the inverted band keeps the heads: in the living-room frame the listeners' heads and the
   room behind them sit between a quarter and a half of the way down, so on the widest bands
   (about 3.3:1) the slice starts a little above them rather than at either edge */
.bleed-top .band-media img{object-position:50% 35%}
/* the underline is navy at 56 percent, 3.51:1 on white, over the 3:1 a link indicator needs */
.panel .ghost{color:var(--navy);border-color:rgba(21,44,94,.56)}
.eyebrow{font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:rgba(21,44,94,.72);margin-bottom:20px}
.media{position:relative;overflow:hidden;height:56svh}
/* the walking figure is in the lower third of the hero frame, so where the media band is wider
   than the photograph (tablets) the slice keeps more of the bottom than the top */
.media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 65%}
@media (min-width:1024px){
  .hero{grid-template-columns:44% 56%;min-height:100svh}
  .media{height:auto}
  .panel{padding:160px var(--pad) 50px}
}
/* the panel widens between 1024 and 1199 so the plain text nav links stay on the white
   panel. Measured: at 44% they cross onto the photograph below 1280 and drop to 6.2:1,
   which passes but breaks the rule that only the toggle and the pill sit on the image. */
@media (min-width:1024px) and (max-width:1279px){
  .hero{grid-template-columns:54% 46%}
}

/* full overlay mobile menu, in site tokens */
.mmenu{
  position:fixed;inset:0;z-index:var(--z-menu);background:var(--dark);color:#fff;
  display:flex;flex-direction:column;padding:20px var(--pad) 40px;
}
.mmenu-top{display:flex;align-items:center;justify-content:space-between}
.mmenu-close{width:44px;height:44px;display:flex;align-items:center;justify-content:center}
.mmenu-close svg{width:18px;height:18px;display:block}
.mmenu nav{margin:auto 0;display:flex;flex-direction:column;align-items:flex-start;gap:24px}
.mmenu nav a{font-size:clamp(30px,8vw,42px);font-weight:600;line-height:1.1}
.mmenu .lang{font-size:14px}

/* shell: 250px rail plus a narrow measure. Cards nearly touch. */
.page{position:relative;z-index:var(--z-page);background:var(--ground)}
.shell{display:flex;flex-direction:column;padding:var(--gap) var(--gap) 0}
.rail{display:block;width:100%;margin-bottom:var(--gap)}
.content{display:flex;flex-direction:column;gap:var(--gap);min-width:0}
@media (min-width:1024px){
  .shell{flex-direction:row;padding:var(--gap)}
  .rail{width:250px;margin:0 80px 0 0;flex-shrink:0;align-self:stretch}
  .content{flex:1;max-width:1360px}
  .page{margin-bottom:var(--reveal)}
}
/* the sticky rail: full height, content bottom aligned. Text only. */
@media (min-width:1024px){
  .rail-inner{
    position:sticky;top:0;height:calc(100vh - 15px);z-index:var(--z-rail);
    display:flex;flex-direction:column;justify-content:flex-end;padding-bottom:25px;
  }
}
/* the rail is a card in the system's own language: ink at 5.5 percent, card radius */
.rail-card{background:var(--card);border-radius:var(--r-card);padding:20px}
/* Narrowing this card to 200px moved the binding constraint. The widest figure, 760.000,
   needs 199px of ink at 56px, and the label and citation were capped at a max-width of
   180px that was sized for the old 202px content box. All three overflowed the card.
   The content box here is 160px, and every one of the five states is measured against it. */
@media (min-width:1024px){ .rail-card{width:200px;margin-inline:auto} }
/* a percentage radius stays correct at any size, which a pixel value does not */
.rail-mark{
  display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:21%;background:var(--raised);margin-bottom:18px;
}
.rail-mark img{width:24px;height:auto}
.rail-stat{font-size:40px;font-weight:400;line-height:.9;letter-spacing:-.04em;color:var(--accent-ink)}
/* the line boxes are reserved for the tallest state so a figure change never moves the
   card and never registers a layout shift */
.rail-label{
  font-size:16px;font-weight:500;line-height:1.15;letter-spacing:-.02em;color:var(--dim);
  margin-top:12px;min-height:56px;
}
.rail-src{margin-top:14px;min-height:30px}
/* below 1024 the card is a static list of all five figures; from 1024 it rotates */
.rail-rotating{display:none}
.rail-list{display:block}
@media (min-width:1024px){
  .rail-rotating{display:block}
  .rail-list{display:none}
}
.rail-row{padding:14px 0;border-top:1px solid var(--hairline)}
.rail-row:first-child{border-top:0;padding-top:0}
.rail-rf{display:block;font-size:34px;font-weight:400;line-height:.9;letter-spacing:-.04em;color:var(--accent-ink)}
.rail-rl{display:block;margin-top:7px;font-size:15px;font-weight:500;line-height:1.15;letter-spacing:-.02em;color:var(--dim)}
.rail-row .t-tiny{display:block;margin-top:7px}

/* the swap moves transform and opacity only */
.tick{transition:transform .2s ease-out,opacity .2s ease-out}

.card{background:var(--card);border-radius:var(--r-card);padding:var(--card-pad)}
.card.white{background:var(--raised)}
.card.dark{background:var(--dark);color:#fff}
.card.dark .t-body{color:rgba(255,255,255,.76)}
.card.dark .t-tiny{color:rgba(255,255,255,.55)}


.two{display:grid;grid-template-columns:minmax(0,1fr);gap:30px}
@media (min-width:1024px){ .two{grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);gap:80px;align-items:start} }
.quote{font-size:24px;font-weight:400;line-height:1.15;letter-spacing:-.04em;max-width:24ch;text-wrap:balance}
@media (min-width:768px){ .quote{font-size:34px} }
.rule{height:1px;background:var(--hairline);border:0;margin:40px 0}
.wide{margin-top:40px}
.fig{overflow:hidden;border-radius:var(--r-card);display:block}
.fig img{width:100%;height:auto;transition:transform .6s ease-out}
.fig:hover img{transform:scale(1.02)}

/* the number band: the opposition is the argument, so the void between is kept */
.band{display:grid;grid-template-columns:repeat(12,1fr);gap:20px;align-items:end}
.band .many{grid-column:1 / span 7}
.band .one{grid-column:9 / span 4;text-align:right}
.band .lbl{display:block;margin-top:12px;font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}
.band .one .t-stat{font-size:30px;color:var(--accent-ink)}
@media (min-width:768px){ .band .one .t-stat{font-size:40px} }
.band-foot{grid-column:1 / span 12;margin-top:40px;padding-top:30px;border-top:1px solid var(--hairline)}
.band-foot .quote{max-width:28ch}
@media (max-width:640px){
  .band .many,.band .one{grid-column:1 / span 12}
  .band .one{text-align:left;margin-top:24px}
}

/* the outline: a schematic Netherlands carrying the single mark. No third party embed,
   no licence question, and no fixed pixel offsets, since the mark is placed in the
   same SVG user space as the outline and scales with it. */
.atlas{display:flex;justify-content:flex-start;padding:30px 0 0}
.map-note{margin-top:16px;max-width:46ch}
/* aspect-ratio reserves the box before paint, so the map cannot shift layout */
.atlas svg{width:100%;max-width:300px;height:auto;display:block;aspect-ratio:300 / 380}
/* --map-line is ink at 55 percent. --hairline-strong measures only 2.14:1 on this white
   card, and these are graphical objects carrying meaning, so they need 3:1. */
.atlas .outline{fill:none;stroke:var(--map-line);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
/* density reads as density: multiply darkens where the Randstad circles overlap, so the
   cluster is legible without moving, jittering or labelling any point */
.atlas .dots{mix-blend-mode:multiply}
.atlas .dot{fill:rgba(26,26,26,.05);stroke:var(--map-line);stroke-width:1.1}
/* The fills animate their radius, not a transform. They used to animate scale with
   transform-box:fill-box and transform-origin:center, and GSAP overwrote that origin with
   0px 0px and wrote its own matrix: matrix(0.8443,0,0,0.8443,-104.102,-137.959) on the
   Amsterdam circle, which solves to 0.8443 x 123.3 - 104.102 = 0. Every fill was being drawn
   at the viewBox origin and clipped away by the coastline, so the beat never rendered at all,
   at any scale value. Radius is also what the animation means. */
.atlas .dotf{fill:var(--accent)}
/* a ground coloured halo separates the accent from the grey outline, so the pairing that
   must pass is accent against ground rather than accent against the stroke */
/* the accent marker animates its radius too, for the same reason */
.atlas .acc-halo{fill:var(--raised)}
.atlas .acc-ring{fill:none;stroke:var(--accent);stroke-width:1.4;opacity:.9}


/* accordion: hairline rows, a plus that loses its stem. Panels are open in the markup
   and closed by CSS only when JS is present, so without JS everything is readable. */
.acc{border-top:1px solid var(--hairline)}
.acc-row{border-bottom:1px solid var(--hairline)}
.acc-btn{width:100%;display:flex;align-items:center;gap:20px;padding:24px 0;text-align:left}
.acc-h{flex:1;font-size:24px;font-weight:600;line-height:1.2;letter-spacing:-.04em;text-wrap:balance}
@media (min-width:768px){ .acc-h{font-size:30px} }
.plus{position:relative;width:22px;height:22px;flex-shrink:0}
.plus::before,.plus::after{content:'';position:absolute;background:var(--ink);transition:transform .3s cubic-bezier(.32,.72,0,1),opacity .3s}
.plus::before{left:0;top:10px;width:22px;height:2px}
.plus::after{top:0;left:10px;width:2px;height:22px}
.acc-btn[aria-expanded="true"] .plus::after{transform:scaleY(0);opacity:0}
.acc-btn:hover .plus::before,.acc-btn:hover .plus::after{background:var(--accent-ink)}
/* height is a layout property and is animated deliberately: click driven, one panel,
   and an accordion cannot push its neighbours without it */
.acc-panel{overflow:hidden;transition:height .3s cubic-bezier(.32,.72,0,1)}
.acc-panel .inner{padding-bottom:24px;max-width:52ch}
.js .acc-panel{height:0}

/* the table makes 25 concrete. Two columns only: we do not know which city holds the
   one Turkish-speaking church, so a third column would invent a fact. */
.cities{width:100%;border-collapse:collapse;margin-top:14px}
.cities caption{caption-side:bottom;text-align:left;margin-top:14px;max-width:70ch}
.cities th,.cities td{padding:11px 0;border-bottom:1px solid var(--hairline);text-align:left}
.cities thead th{
  font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;
  color:var(--dim);border-bottom:1px solid var(--hairline-strong);
}
.cities td.num,.cities th.num{text-align:right;font-variant-numeric:tabular-nums}
.js .cities tbody tr[data-more]{display:none}
.js .cities[data-open="true"] tbody tr[data-more]{display:table-row}
.showall{
  margin-top:18px;font-size:14px;font-weight:500;letter-spacing:-.02em;
  border-bottom:1px solid var(--hairline-strong);padding-bottom:2px;cursor:pointer;
}
.showall:hover{border-color:var(--accent-ink)}
.js .showall{display:inline-block}
.showall{display:none}

/* the two giving routes, as rows. The arrow answers a hover on the whole row. */
.routes{margin-top:30px}
.route{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:18px 0;border-top:1px solid rgba(255,255,255,.18);
}
.route:last-child{border-bottom:1px solid rgba(255,255,255,.18)}
.route-arrow{width:14px;height:14px;flex-shrink:0;transition:transform .15s cubic-bezier(.4,0,.2,1)}
.route:hover .route-arrow{transform:rotate(45deg)}
.route-arrow svg{display:block;width:14px;height:14px}

/* contact: an honest line, not a control that looks functional and is not */
.contact-note{margin-top:20px;max-width:44ch}

/* footer, and the reveal. From 1024 the footer is fixed behind the page and the page
   reserves its depth, so the content slides up off it at the end. No JS, no pin. */
.foot{background:var(--dark);color:#fff;padding:60px var(--pad) 30px}
.foot-grid{max-width:1360px;margin:0 auto;display:flex;justify-content:space-between;gap:60px;flex-wrap:wrap}
.foot-brand{display:flex;align-items:center;gap:12px}
.foot-brand img{width:88px;height:auto;display:block}
.foot-note{margin-top:20px;max-width:44ch;color:rgba(255,255,255,.62)}
.foot-links{display:flex;flex-direction:column;gap:12px;align-items:flex-start}
.foot-links a{font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.82)}
.foot-bottom{
  max-width:1360px;margin:50px auto 0;padding-top:20px;border-top:1px solid rgba(255,255,255,.18);
  display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;color:rgba(255,255,255,.55);
}
@media (min-width:1024px){
  .foot{position:fixed;bottom:0;left:0;right:0;z-index:var(--z-reveal);padding:var(--reveal) var(--pad) 30px}
  /* The reveal works by letting .page slide up off this fixed footer. That leaves the
     footer's controls in the tab order while they are still covered by the opaque .page,
     so a keyboard user was focusing links they could not see. :focus-within lifts the
     footer the moment focus enters it and drops it again on the way out. CSS only, so a
     failed CDN cannot strand the footer either above or below the page. */
  /* :focus-within was the wrong test. It matches a mouse click too, so clicking the
     footer's own language switch focused the button, lifted the footer above .page, and
     left it there, pasted over the whole page at every scroll position, because scrolling
     does not blur a button. The lift only ever existed for keyboard users, and
     :focus-visible is the selector that means keyboard: it does not match a mouse click on
     a button. Where :has is unsupported the rule drops out and the footer simply never
     lifts, which is the old behaviour rather than a broken one. */
  .foot:has(:focus-visible){z-index:var(--z-footfocus)}
  /* Lifting it is not enough on its own. The footer's blocks are held at opacity 0 by the
     gsap.from entrance until the reveal fires, so a keyboard user arriving early would be
     shown an empty bar. Focus completes the entrance as well as lifting it. */
  .foot:has(:focus-visible) [data-r]{opacity:1!important;transform:none!important;filter:none!important}
}

@media (max-width:900px){
  .nav-links{display:none}
  .nav .lang{display:none}
  .menu-btn{display:flex}
  .nav{gap:16px;padding:16px var(--pad)}
  .pill{padding:12px 20px;font-size:14px}
  .brand b{font-size:11px}
  .brand img{width:32px}
  .foot-grid{flex-direction:column;gap:30px}
}
@media (max-width:900px){ .nav-ticker{max-width:132px;font-size:11px} }
@media (max-width:359px){ .nav-ticker{display:none} }
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{transition-duration:.01ms!important;animation:none!important}
  html{scroll-behavior:auto}
}

/* ============================================================================
   Round 14: the site became multi page. Everything below is shared shell or the
   Doneren page's own arrangements. Locked decisions hold: the token set, the
   weight ceiling of 600, -.04em on display type, radius from --r-card so it
   grows with the viewport, surfaces as ink at low opacity, and the accent at
   full strength in only a few places.
   ============================================================================ */

.t-mid{font-size:24px;font-weight:600;line-height:1.2;letter-spacing:-.04em;text-wrap:balance}
.mt-30{margin-top:30px}
.mb-30{margin-bottom:30px}

/* Pages other than home have no hero, so they carry a compact dark masthead. It uses the
   same surface and the same padding rhythm as the hero's panel, which lets the shared nav
   keep its white on dark treatment without a second set of rules. */
/* This used to be 150px of padding above a single 46ch column, which is the hero's height and
   the hero's column without the hero's photograph, so the right two thirds read as a missing
   image. It is now a header band: less height, and the heading and the lead sit side by side
   in the same two column rhythm the cards use, so the width is spent rather than left over. */
.pagehead{position:relative;background:var(--raised);color:var(--navy);padding:104px var(--pad) 36px}
.pagehead .t-body{color:rgba(21,44,94,.78)}
.pagehead-in{max-width:36ch}
@media (min-width:1024px){
  .pagehead{padding:118px var(--pad) 44px}
  .pagehead-in{
    max-width:none;display:grid;grid-template-columns:minmax(0,7fr) minmax(0,9fr);
    gap:60px;align-items:end;
  }
  .pagehead-in .eyebrow{grid-column:1 / -1;margin-bottom:0}
  .pagehead-in .t-body{max-width:46ch;padding-bottom:.35em}
}

/* The current page. In the link list the underline that hover draws is simply left drawn.
   The Doneren pill cannot use an underline, so on its own page it takes a navy ring on
   the white header: a border, not a glow. */
.nav-links a[aria-current="page"]::after,.mmenu nav a[aria-current="page"]::after{transform:scaleX(1)}
.nav-links a[aria-current="page"]{color:var(--navy)}
.pill[aria-current="page"]{box-shadow:0 0 0 2px rgba(21,44,94,.3)}

/* A placeholder must never be mistaken for content, so every one of them is dimmed as well
   as bracketed. The sweep before this goes live is the data-placeholder list. */
[data-placeholder]{color:var(--dim)}
.card.dark [data-placeholder]{color:rgba(255,255,255,.62)}
.pagehead [data-placeholder]{color:rgba(21,44,94,.72)}
/* IBAN with its copy button. The button is 32px square for touch but pulls in its vertical
   margin, so the row keeps the height the plain line had. */
.iban{display:flex;align-items:center;flex-wrap:wrap;gap:4px 6px}
.iban-v{color:var(--ink);font-weight:500;letter-spacing:0}
.copy-btn{
  display:inline-grid;place-items:center;width:32px;height:32px;margin:-10px 0;padding:0;
  border:0;border-radius:50%;background:transparent;color:var(--ink);cursor:pointer;
  transition:background-color .2s,color .2s;
}
.copy-btn[hidden]{display:none}
.copy-btn:hover{background:var(--accent-wash);color:var(--accent-ink)}
.copy-btn svg{grid-area:1 / 1;width:15px;height:15px;transition:opacity .2s,transform .2s}
.copy-btn .i-check{opacity:0;transform:scale(.6);color:var(--accent-ink)}
.copy-btn.is-done .i-copy{opacity:0;transform:scale(.6)}
.copy-btn.is-done .i-check{opacity:1;transform:none}
.copy-ok{color:var(--accent-ink);opacity:0;transition:opacity .2s}
.copy-ok.is-on{opacity:1}
@media (prefers-reduced-motion:reduce){.copy-btn,.copy-btn svg,.copy-ok{transition:none}}

/* Doneren, card 2: the two routes as equal columns, a nested raised surface each */
.routes2{display:grid;gap:var(--gap);grid-template-columns:1fr}
@media (min-width:768px){ .routes2{grid-template-columns:1fr 1fr;gap:30px} }
.route2{background:var(--raised);border-radius:var(--r-card);padding:30px}
@media (min-width:1024px){ .route2{padding:40px} }

/* Doneren, card 3: one statement across the card's whole width, no side heading */
.eyebrow-ink{font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);margin-bottom:20px}
.statement{font-size:24px;font-weight:400;line-height:1.3;letter-spacing:-.04em;max-width:52ch;text-wrap:balance}
@media (min-width:768px){ .statement{font-size:28px} }

/* Doneren, card 4: a numbered sequence, a row of four at desktop and stacked below.
   The numerals are ink at 65 percent rather than the accent, because four accent numerals
   would spend the accent in a place that does not need it. */
.flow{list-style:none;display:grid;gap:var(--gap);margin:0;padding:0}
@media (min-width:768px){ .flow{grid-template-columns:repeat(4,1fr);gap:24px} }
.flow-step{display:flex;gap:16px;align-items:baseline;background:var(--raised);border-radius:var(--r-card);padding:24px}
@media (min-width:768px){ .flow-step{flex-direction:column;gap:18px;align-items:flex-start} }
.flow-n{font-size:34px;font-weight:400;line-height:.9;letter-spacing:-.04em;color:var(--dim);flex-shrink:0}
.flow-t{font-size:16px;font-weight:500;line-height:1.3;letter-spacing:-.02em}

/* Doneren, card 5: label and value rows for what is still missing */
.needs{border-top:1px solid var(--hairline)}
.need-row{display:flex;justify-content:space-between;align-items:baseline;gap:24px;padding:14px 0;border-bottom:1px solid var(--hairline)}
.need-k{font-size:16px;font-weight:400;line-height:1.3;letter-spacing:-.02em}
.need-v{font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;flex-shrink:0;white-space:nowrap}

/* The rail on a page with no sections: one fixed figure, shown at every width */
.rail-fixed .rail-label{margin-top:12px}
.rail-fixed .rail-src{margin-top:14px;min-height:0}

/* Round 15. The fill beat was invisible: the fills reached half the radius of circles whose
   radii are 4 to 8 units on a 300 unit map, so they inked in at one to four device pixels.
   They now go to full radius in the timeline. mix-blend-mode stays on the group: sampled at
   the centre of the accent marker and three Randstad circles it shifts the colour by
   0, 0, 0, and across the whole render it changes 1.13 percent of pixels, all of them grey
   on grey where a circle's outline crosses the coastline, which is the density reading it
   was added for. It was never what hid the fills. */

/* ---- Demografie: the map at the size it deserves, and the figures listed with citations ---- */
/* the atlas caps itself at 300px for the home card; here it takes the column */
.atlas-lg .atlas{padding:0}
.atlas-lg .atlas svg{max-width:none;width:100%}
@media (min-width:768px){ .atlas-lg{max-width:560px} }
@media (min-width:1024px){ .atlas-lg{max-width:640px} }
/* every row of the table shows on this page, so the control is not rendered at all */
.js .cities-all .cities tbody tr[data-more]{display:table-row}
/* the remaining figures, one row each, figure and label and citation */
.figs{border-top:1px solid var(--hairline)}
.fig-row{display:grid;grid-template-columns:1fr;gap:4px;padding:20px 0;border-bottom:1px solid var(--hairline)}
@media (min-width:768px){ .fig-row{grid-template-columns:150px 1fr 260px;gap:24px;align-items:baseline} }
/* ink, not accent: five accent numerals on one card would spend a colour the site uses in
   only a few places, and at 34px these read as figures without it */
.fig-n{font-size:34px;font-weight:400;line-height:.9;letter-spacing:-.04em;color:var(--ink)}
.fig-l{font-size:16px;font-weight:500;line-height:1.3;letter-spacing:-.02em}
@media (min-width:768px){ .fig-s{text-align:right} }

/* ---- Round 16: the third column. The client asked for something that shows the dearth in
   the other cities and how alone Rotterdam is. Each row carries a small circle, the same mark
   the map uses: hollow for the 24, filled with the accent for Rotterdam, which is the only row
   in the table that takes any colour. The header says as far as we know, because the 24 noes
   are the foundation's own knowledge rather than a survey. The word travels with the mark so
   the meaning never depends on colour or shape alone. */
.cities th:first-child,.cities td:first-child{padding-left:10px}
.cities th:last-child,.cities td:last-child{padding-right:10px}
.cities th.kerk,.cities td.kerk{text-align:right;padding-left:14px;white-space:nowrap}
.cities th.kerk{white-space:normal;max-width:9em}
.cities td.num{padding-left:10px}
.cities .kerk-sub{display:block;margin-top:3px;font-size:10px;letter-spacing:.03em;text-transform:none;font-weight:400}
.cities td.kerk{color:var(--dim)}
.kerk-dot{display:inline-block;width:9px;height:9px;border-radius:50%;border:1px solid var(--map-line);margin-right:8px;vertical-align:.02em}
.cities tr.is-rdam{background:var(--accent-wash)}
.cities tr.is-rdam td{color:var(--accent-ink);font-weight:500}
.cities tr.is-rdam .kerk-dot{background:var(--accent);border-color:var(--accent)}
@media (max-width:479px){
  .cities td{font-size:14px}
  .cities thead th{font-size:10px;letter-spacing:.03em}
  .cities th.kerk,.cities td.kerk{padding-left:8px}
  .kerk-dot{margin-right:5px}
}

/* ---- Round 16: contact form. Field borders are ink at 48 percent, 3.15:1 on white, the
   same value the ghost underline uses, so an empty field is visible as a field. The error
   state doubles the border and switches it to the accent, 6.44:1, and the message sits under
   the field in the accent too, so the error never relies on colour alone: the border also
   thickens and the words say what to do. */
.addr{font-style:normal;font-size:16px;line-height:1.45;letter-spacing:-.02em}
.contact-addr .t-label{color:var(--dim);margin-bottom:6px}
.cform{display:grid;gap:20px;max-width:560px}
.cf-field label{display:block;font-size:14px;font-weight:500;line-height:1.2;margin-bottom:8px}
.cf-field input,.cf-field textarea{
  display:block;width:100%;font:inherit;font-size:16px;line-height:1.4;color:var(--ink);
  background:var(--raised);border:1px solid rgba(26,26,26,.48);border-radius:var(--r-btn);
  padding:12px 14px;
}
.cf-field textarea{min-height:150px;resize:vertical}
.cf-field input:focus-visible,.cf-field textarea:focus-visible{outline:2px solid var(--accent-ink);outline-offset:2px;border-color:var(--ink)}
.cf-field [aria-invalid="true"]{border:2px solid var(--error);padding:11px 13px}
.cf-err{margin-top:7px;font-size:14px;line-height:1.3;color:var(--error)}
.cf-err[hidden]{display:none}
.hp{display:none!important}
.cf-actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px 20px}
/* Versturen is a pill but not a gift, so it takes the teal and keeps red for Doneren alone */
.cf-send{background:var(--accent-ink)}
.cf-send::after{background:var(--navy)}
.cf-send[disabled]{opacity:.6;cursor:progress}
.cf-status{margin:0;font-size:15px;line-height:1.35;flex:1 1 220px}
.cf-status[data-state="busy"]{color:var(--dim)}
.cf-status[data-state="err"],.cf-status[data-state="warn"]{color:var(--error)}
.foot .addr{margin-top:18px;color:rgba(255,255,255,.78);font-size:15px}

/* ---- Round 16: the ANBI register and the resolved rows on Doneren ---- */
.reg{margin:0;border-top:1px solid var(--hairline)}
.reg-row{display:grid;grid-template-columns:1fr;gap:4px;padding:14px 0;border-bottom:1px solid var(--hairline)}
@media (min-width:600px){ .reg-row{grid-template-columns:9em 1fr;gap:24px;align-items:baseline} }
.reg dt{font-size:14px;font-weight:500;letter-spacing:-.01em;color:var(--dim)}
.reg dd{margin:0;font-size:16px;line-height:1.4;letter-spacing:-.02em}
/* a row that has been answered reads as an answer: ink, sentence case, allowed to wrap */
/* a known value is a sentence, not a tag: it may shrink and wrap, where [volgt] never needs to */
.need-v.is-known{text-transform:none;letter-spacing:-.02em;font-size:16px;font-weight:400;white-space:normal;text-align:right;flex-shrink:1}
