/* objectvision.nl — direction A, "Raster".
   Built from the thing the models actually compute on. The palette comes from Dutch
   land-use cartography: brick for built-up, moss for nature, wheat for agriculture, water
   blue. Strict modular grid, hairline rules, technical numerals in the margin. */

:root{
  --ground:#f1f4f2;
  --sheet:#e7ece9;
  --ink:#141f1b;
  --mut:#5a6b64;
  --line:#ccd6d1;

  /* Object Vision's own colour, from the folded map in the logo (#fdc070). Straight out of
     the logo it has a contrast of 1.5 against this paper, so it works as a fill and not as a
     letter. Hence two tones along the same hue, each doing what it can carry.

     --gold is the wordmark and the one accented word in the hero heading. Contrast 2.3, which
     is fine for a logotype (exempt) and generous for a word set at 50 pixels.
     --accent is everything that is actually read: links, list markers, labels. Contrast 5.7,
     comfortably past the 4.5 that small text needs. */
  --gold:#e08f10;
  --accent:#8d5102;

  /* The land-use classes. Cartography rather than branding: brick is what built-up is on a
     Dutch land-use map, and the diagrams use these for that. Not interchangeable with the
     accent above, which is why they are separate now. */
  --urban:#b4472f;
  --nature:#4a7a4e;
  --agri:#cbb069;
  --water:#2e6b8a;

  --measure:66ch;
  color-scheme:light;   /* deliberate: one visual world, in any system theme */
}

*{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
  margin:0; background:var(--ground); color:var(--ink);
  font-family:"Segoe UI",system-ui,-apple-system,"Helvetica Neue",sans-serif;
  font-size:17px; line-height:1.6;
  font-kerning:normal; text-rendering:optimizeLegibility;
}
.wrap{ max-width:78rem; margin:0 auto; padding:0 2rem; }

/* clipped rather than pushed off-screen, so it can never widen the page */
.skip{ position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap; }
.skip:focus{ width:auto; height:auto; clip-path:none; left:1rem; top:1rem;
  background:var(--ink); color:var(--ground); padding:.5rem .9rem; z-index:10; }

/* ---------- masthead ---------- */
.masthead{ border-bottom:1px solid var(--line); }
.masthead-inner{ display:flex; align-items:baseline; gap:2rem; padding:1.4rem 2rem;
  flex-wrap:wrap; }
.logo{ font-size:1.05rem; font-weight:700; letter-spacing:-.03em; color:var(--ink);
  text-decoration:none; margin-right:auto; }
.logo:hover{ color:var(--accent); }

.nav{ display:flex; gap:1.5rem; align-items:baseline; flex-wrap:wrap; }
.nav a{ color:var(--mut); text-decoration:none; font-size:.87rem; padding-bottom:.15rem;
  border-bottom:1.5px solid transparent; }
.nav a:hover,.nav a:focus-visible{ color:var(--accent); border-bottom-color:var(--accent); }
.nav a.on{ color:var(--ink); border-bottom-color:var(--ink); }

/* The submenu sits a little below its parent. That gap has to belong to the hoverable area,
   otherwise the menu closes the moment the pointer crosses it on the way down. The short
   visibility delay forgives a diagonal mouse path along the edge. */
.nav-group{ position:relative; padding-bottom:.6rem; margin-bottom:-.6rem; }
.nav-drop{ position:absolute; left:0; top:100%; background:#fff;
  border:1px solid var(--line); padding:.4rem 0; min-width:17rem; z-index:5;
  visibility:hidden; opacity:0;
  transition:visibility 0s linear .2s, opacity .12s ease; }
.nav-group:hover .nav-drop,.nav-group:focus-within .nav-drop{
  visibility:visible; opacity:1; transition-delay:0s; }
/* the right-most group opens to the left, otherwise its panel runs off the page */
.nav-group:last-of-type .nav-drop{ left:auto; right:0; }
.nav-drop a{ display:block; padding:.4rem 1rem; font-size:.87rem; border-bottom:none; }
.nav-drop a:hover{ background:var(--sheet); }

/* ---------- sheet: margin column + measure ---------- */
main{ padding:0 0 4rem; overflow-x:clip; position:relative; }
main > .wrap{ position:relative; z-index:1; }
/* The reading column is capped well below the width of the sheet, because a line of 150
   characters cannot be read. Left-aligned that left a wide empty strip on the right, which
   looks like a mistake rather than like a margin. Centring the columns puts the same space on
   both sides, where it reads as margin. The margin column travels with the text, so the
   timeline stays attached to what it annotates instead of drifting off on its own. */
.sheet{ display:grid; grid-template-columns:12rem minmax(0,var(--measure)); gap:3rem;
  justify-content:center; position:relative; padding-top:3.2rem; }

/* the margin column reads as an instrument panel: mono, tabular, hairline separated */
.margin-note{ font-family:Consolas,"Cascadia Mono","SF Mono",Menlo,monospace;
  font-size:.74rem; color:var(--mut); line-height:1.45;
  border-top:1px solid var(--ink); padding-top:.8rem; }
.margin-note div{ position:relative; padding:0 0 .85rem 0; }
.margin-note div:last-child{ padding-bottom:0; }
.margin-note b{ display:block; color:var(--accent); font-weight:400; font-size:.78rem;
  letter-spacing:.04em; font-variant-numeric:tabular-nums; margin-bottom:.15rem; }
.measure{ max-width:var(--measure); position:relative; }

h1{ font-size:clamp(2rem,4.4vw,3.1rem); line-height:1.03; font-weight:700;
  letter-spacing:-.04em; margin:0 0 .7rem; text-wrap:balance; }
.tagline{ font-size:1.08rem; color:var(--mut); margin:0 0 1.3rem; }
.tagline:empty{ display:none; }
.rule{ height:1px; background:var(--line); margin:0 0 1.8rem; }

/* ---------- the raster on the home page ---------- */
/* The hero figure carries its own labels and its own animation, from css inside the svg. */
.hero-figure{ margin:0; }
.hero-figure img{ display:block; width:100%; height:auto; max-width:34rem;
  margin-left:auto; margin-right:auto; }

/* ---------- prose ---------- */
.prose > *:first-child{ margin-top:0; }
.prose p,.prose ul,.prose ol{ margin:0 0 1.15rem; }

/* Justified running text. Without hyphenation a justified column pulls words apart to reach
   the right edge and the white gaps line up into rivers down the page, which is worse than a
   ragged edge; with it the browser breaks long words instead and the spacing stays even. It
   needs the lang on <html>, which is there. Only paragraphs: a justified list item or caption
   is usually one or two lines, where justifying stretches a handful of words across the whole
   measure. The last line of a paragraph stays left, which is the default. */
.prose p{ text-align:justify; -webkit-hyphens:auto; hyphens:auto; }
/* On a phone the column is about 36 characters wide. Justifying that few words to a fixed
   width opens gaps you can drive a car through, so below this width the edge goes ragged. */
@media (max-width:560px){
  .prose p{ text-align:left; }
}
.prose h2{ font-size:1.32rem; font-weight:700; letter-spacing:-.02em; margin:2.5rem 0 .8rem;
  padding-top:.9rem; border-top:1px solid var(--ink); text-wrap:balance; }
.prose h3{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.76rem;
  letter-spacing:.08em; text-transform:uppercase; color:var(--accent); font-weight:400;
  margin:1.9rem 0 .5rem; }
.prose a{ color:var(--accent); text-decoration:none; border-bottom:1px solid var(--line); }
.prose a:hover,.prose a:focus-visible{ border-bottom-color:var(--accent); }
.prose strong{ font-weight:600; }
.prose ul,.prose ol{ padding-left:1.15rem; }
.prose li{ margin-bottom:.45rem; }
.prose li::marker{ color:var(--accent); }
.prose blockquote{ margin:1.4rem 0; padding-left:1.1rem; border-left:2px solid var(--accent);
  color:var(--mut); }
.prose code{ font-family:Consolas,"SF Mono",Menlo,monospace; font-size:.88em;
  background:var(--sheet); padding:.1em .35em; }
/* No frame. The diagrams are drawings on the same paper as the page, and a hairline box around
   them turned each one into a pasted-in illustration. */
.prose img{ max-width:100%; height:auto; display:block; margin:1.6rem 0; }
.prose figure{ margin:1.6rem 0; }
.prose figure img{ margin:0; }
.prose figcaption{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.72rem;
  color:var(--mut); padding-top:.5rem; }
.prose hr{ border:none; border-top:1px solid var(--ink); margin:2.2rem 0; }

.prose table{ width:100%; border-collapse:collapse; margin:1.5rem 0; font-size:.92rem;
  font-variant-numeric:tabular-nums; }
.prose thead th{ text-align:left; font-family:Consolas,"Cascadia Mono",monospace;
  font-size:.7rem; letter-spacing:.07em; text-transform:uppercase; color:var(--mut);
  font-weight:400; border-bottom:1px solid var(--ink); padding:.5rem .8rem .5rem 0; }
.prose td{ border-bottom:1px solid var(--line); padding:.6rem .8rem .6rem 0;
  vertical-align:top; }
.prose td:last-child,.prose th:last-child{ padding-right:0; }
.table-scroll{ overflow-x:auto; }

/* ---------- footer ---------- */
.foot{ border-top:1px solid var(--ink); margin-top:2rem; }
.foot-inner{ display:grid; grid-template-columns:repeat(4,1fr); gap:2rem;
  padding:2.2rem 2rem 3rem; font-size:.85rem; color:var(--mut); line-height:1.6; }
.foot a{ color:var(--mut); text-decoration:none; border-bottom:1px solid var(--line); }
.foot a:hover{ color:var(--accent); border-bottom-color:var(--accent); }
.foot strong{ color:var(--ink); font-weight:600; }
.colophon{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.72rem; }

/* ---------- home ---------- */
body.home h1{ font-size:clamp(2.2rem,5vw,3.5rem); max-width:18ch; }
body.home .tagline{ font-size:1.18rem; }

@media (max-width:900px){
  .sheet{ grid-template-columns:1fr; gap:1.6rem; padding-top:2.2rem; }
  /* The margin column is a summary that stands next to the text it summarises. Once the two
     columns collapse it stops standing next to anything and becomes a list of dates you read
     before the story that explains them, which the story then repeats. Off. */
  .margin-col{ display:none; }
  .foot-inner{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:560px){
  body{ font-size:16px; }
  .wrap{ padding-left:1.25rem; padding-right:1.25rem; }
  .masthead-inner{ padding:1.1rem 1.25rem; }
  .nav{ gap:1rem; }
  .foot-inner{ grid-template-columns:1fr; padding:1.8rem 1.25rem 2.4rem; }
  /* the submenu would make the header 400px tall on a phone; the section index at
     /what-we-do/ lists the same pages, so the top-level link is enough here */
  .nav-drop{ display:none; }
  .nav-group{ padding-bottom:0; margin-bottom:0; }
}
@media (prefers-reduced-motion:reduce){
  *{ animation:none !important; transition:none !important; }
}

/* ---------- client band ---------- */
/* Names, not logos: every client logo needs permission, and the UN and EU emblems are
   protected outright. A typographic band also sits better with the rest of the page. */
.clients{ border-top:1px solid var(--ink); background:var(--sheet); }
.clients .wrap{ padding-top:1.8rem; padding-bottom:2.2rem; }
.clients-label{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.7rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--accent); margin:0 0 1.2rem; }
.client-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:1px;
  background:var(--line); border:1px solid var(--line); }
.client{ background:var(--sheet); padding:.9rem 1rem 1rem; display:flex;
  flex-direction:column; gap:.35rem; }
.cn{ font-size:.95rem; font-weight:600; line-height:1.25; letter-spacing:-.01em; }
.cd{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.68rem; color:var(--mut);
  line-height:1.4; }

@media (max-width:900px){
  .client-grid{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:560px){
  .client-grid{ grid-template-columns:1fr; }
  .clients .wrap{ padding-bottom:1.6rem; }
}

/* ---------- home: hero, cards ---------- */
.logo span{ color:var(--gold); }

.hero{ display:grid; grid-template-columns:1fr 1fr; gap:3.5rem; align-items:center;
  padding-top:4rem; padding-bottom:3.5rem; }
.hero h1{ font-size:clamp(2.2rem,4.6vw,3.4rem); line-height:1.02; letter-spacing:-.045em;
  margin:0 0 1.1rem; max-width:14ch; }
.hero h1 em{ font-style:normal; color:var(--gold); }
.hero .lead{ font-size:1.05rem; color:var(--mut); margin:0 0 1.8rem; max-width:44ch;
  line-height:1.55; }
.cta{ display:flex; gap:.7rem; flex-wrap:wrap; }
.btn{ display:inline-block; padding:.65rem 1.2rem; font-size:.92rem; text-decoration:none;
  border:1px solid var(--ink); color:var(--ink); }
.btn.solid{ background:var(--ink); color:var(--ground); }
.btn:hover,.btn:focus-visible{ background:var(--accent); border-color:var(--accent); color:#fff; }

.hero-raster{ min-width:0; }

/* six domains, on the modular grid */
.cards{ display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.card{ background:var(--ground); padding:1.5rem 1.6rem 1.8rem; text-decoration:none;
  display:flex; flex-direction:column; gap:.45rem; }
.card:hover{ background:var(--sheet); }
/* the label above each card is 11px mono. A warm colour at that size turns muddy, and
   there are six of them in a row, so it reads as a stain rather than as an accent. Neutral. */
.card-n{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.7rem; color:var(--mut);
  letter-spacing:.07em; }
.card-h{ font-size:1.05rem; font-weight:600; letter-spacing:-.02em; color:var(--ink); }
.card-t{ font-size:.9rem; color:var(--mut); line-height:1.5; }

.home-prose{ max-width:var(--measure); padding:3rem 0 1rem; }

@media (max-width:900px){
  .hero{ grid-template-columns:1fr; gap:2rem; padding-top:2.5rem; }
  .hero h1{ max-width:18ch; }
  .cards{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:560px){
  .cards{ grid-template-columns:1fr; }
}

/* Pages without a margin column are a single column: repeating the same timeline everywhere
   is noise, and an empty third of the width looks like a mistake rather than a choice. */
.sheet.nomargin{ grid-template-columns:minmax(0,41.25rem); }
.sheet.nomargin .margin-col{ display:none; }
.sheet.nomargin .measure{ max-width:72ch; }

/* The paragraph under the six cards sat alone at the far left with two thirds empty.
   It now shares the same three column grid the cards use. */
.home-prose{ max-width:none; display:grid; grid-template-columns:repeat(3,1fr); gap:3rem;
  padding:3rem 0 1rem; }
.home-prose .prose{ grid-column:span 2; }
.home-note{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.74rem; color:var(--mut);
  line-height:1.6; border-top:1px solid var(--ink); padding-top:.8rem; }
.home-note a{ color:var(--accent); text-decoration:none; border-bottom:1px solid var(--line); }
@media (max-width:900px){
  .home-prose{ grid-template-columns:1fr; gap:1.6rem; }
  .home-prose .prose{ grid-column:auto; }
}

/* ---------- news ---------- */
/* The list is generated from the files in content/news/, so an item is added by adding a
   file. The date column is mono and tabular, like the margin timeline it echoes. */
.news-list{ border-top:1px solid var(--ink); margin:1.6rem 0 0; }
.news-item{ display:grid; grid-template-columns:9rem minmax(0,1fr); gap:1.5rem;
  padding:1.1rem 0 1.2rem; border-bottom:1px solid var(--line); text-decoration:none;
  color:inherit; align-items:baseline; }
.news-item:hover{ background:var(--sheet); }
.news-date{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.72rem;
  color:var(--accent); letter-spacing:.04em; font-variant-numeric:tabular-nums; }
.news-title{ font-size:1.05rem; font-weight:600; letter-spacing:-.02em; line-height:1.3;
  text-wrap:balance; }
.news-blurb{ grid-column:2; font-size:.9rem; color:var(--mut); line-height:1.5;
  max-width:60ch; padding-top:.3rem; }
.news-stamp{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.72rem;
  color:var(--accent); letter-spacing:.04em; margin:0 0 1.4rem; }
@media (max-width:560px){
  .news-item{ grid-template-columns:1fr; gap:.3rem; }
  .news-blurb{ grid-column:auto; }
}

/* the three most recent items, at the foot of the home page */
.latest{ border-top:1px solid var(--ink); }
.latest .wrap{ padding-top:1.8rem; padding-bottom:2.4rem; }
.latest .news-list{ border-top:none; margin:0; }
.latest .news-item:first-child{ border-top:1px solid var(--line); }
.latest-more{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.72rem;
  letter-spacing:.04em; margin:1rem 0 0; }
.latest-more a{ color:var(--accent); text-decoration:none;
  border-bottom:1px solid var(--line); }
.latest-more a:hover{ border-bottom-color:var(--accent); }

/* the map on the contact page: an openstreetmap embed, which sets no cookies and so needs
   no consent banner. The frame-src in .htaccess names that one host and nothing else. */
.map{ margin:1.6rem 0; }
.map iframe{ display:block; width:100%; height:26rem; border:1px solid var(--line); }
.map figcaption{ font-family:Consolas,"Cascadia Mono",monospace; font-size:.72rem;
  color:var(--mut); padding-top:.5rem; }
.map figcaption a{ color:var(--accent); text-decoration:none;
  border-bottom:1px solid var(--line); }

/* A diagram written into the page rather than loaded as a picture, so its boxes can be links.
   The svg has to be told to behave like a block image; without the width it takes its own
   intrinsic size and stops scaling with the column. */
.prose figure.diagram{ margin:1.6rem 0; }
.prose figure.diagram svg{ display:block; width:100%; height:auto; }
