/* Cabineteer website — derived component styles on top of the source tokens (css/tokens.css).
   Fonts are the packaged OFL files; spacing 4/8/16/24/32/48/80; controls 4px radius, panels 0. */
@font-face{font-family:"Manrope";src:url("../fonts/Manrope-Variable.ttf") format("truetype");font-weight:200 800;font-display:swap}
@font-face{font-family:"IBM Plex Mono";src:url("../fonts/IBMPlexMono-Regular.ttf") format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"IBM Plex Mono";src:url("../fonts/IBMPlexMono-Medium.ttf") format("truetype");font-weight:500;font-display:swap}
*{box-sizing:border-box}
html{background:var(--c-paper);color:var(--c-ink)}
body{margin:0;font:var(--c-type-body-weight) var(--c-type-body-size)/var(--c-type-body-line) var(--c-type-body-family),system-ui,sans-serif}
a{color:var(--c-ink)} :focus-visible{outline:3px solid var(--c-ink);outline-offset:3px}
.wrap{max-width:1328px;margin:0 auto;padding:0 56px} @media(max-width:720px){.wrap{padding:0 20px}}
.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}
/* header */
.site-header{background:var(--c-surface);border-bottom:1px solid var(--c-dividerDecorative)}
/* two-row desktop header (T-Q35, QA-02). The old single row never fit: logo, seven
   links and the CTA needed more than the capped 1216px content area (1328 - 2x56), so
   the nav wrapped at every width (evidence/M1b/T-Q30-header-nav-wrap-defect.png).
   Row 1 is the logo and the CTA; row 2 is the nav, forced onto its own line by
   flex-basis:100%. Markup order is logo, toggle, cta, nav on all 13 pages, so the DOM
   order matches the visual order and no CSS `order` is used. The seven links need
   973px on one line (829px measured + 6 x 24px gaps); the content area is the viewport
   minus 112px, which first clears that at 1091px. Below that, the mobile disclosure
   covers it. Vivek chose the two-row header; extending the breakpoint instead of
   squeezing the spacing was the lead's instruction. */
.site-header .wrap{display:flex;flex-wrap:wrap;align-items:center;gap:16px 32px;padding-top:16px;padding-bottom:16px}
.site-header .logo img{height:40px;width:auto;display:block}
.nav-toggle{display:none}
.site-header .cta{background:var(--c-ink);color:#fff;padding:12px 20px;border-radius:var(--c-radius);border:0;min-height:48px;display:inline-flex;align-items:center;text-decoration:none;font:var(--c-type-button-weight) var(--c-type-button-size)/var(--c-type-button-line) var(--c-type-button-family);margin-left:auto}
.site-header .cta:hover{background:var(--c-action-hover)}
.nav{display:flex;gap:24px;flex-wrap:wrap;flex-basis:100%} .nav a{text-decoration:none;font-weight:600;font-size:16px;padding:8px 0;border-bottom:2px solid transparent} .nav a[aria-current=page]{border-bottom-color:var(--c-ink)}
/* mobile header (QA-02, extended by T-Q35): below 1090px the desktop row above does
   not fit (see the note above `.site-header .wrap`), so this threshold now covers both
   the original small-phone range and the in-between laptop/tablet range where 8 items
   never fit the header's capped width. Row 1 is logo+toggle; the CTA becomes its own
   full-width row (still always visible, not gated by the toggle); the nav stays a
   disclosure driven by js/nav.js, pushed into normal flow rather than an overlay, so
   it needs no focus trap and never causes horizontal overflow. Closed nav still has
   zero focusable targets (T-Q04): the CTA sits outside <nav> now, so it is unaffected
   by nav[hidden] either way. */
@media(max-width:1090px){
  .site-header .wrap{gap:12px;min-height:64px;padding-top:12px;padding-bottom:12px}
  .site-header .logo img{height:28px}
  .nav-toggle{display:flex;align-items:center;justify-content:center;width:48px;height:48px;margin-left:auto;padding:0;border:1px solid var(--c-controlBorder);border-radius:var(--c-radius);background:var(--c-surface);color:var(--c-ink)}
  .nav-toggle:hover{background:var(--c-tint)}
  .nav-toggle[aria-expanded=true]{background:var(--c-tint)}
  .site-header .cta{flex-basis:100%;margin-left:0;justify-content:center}
  .nav[hidden]{display:none}
  .nav{width:100%;flex-direction:column;align-items:stretch;gap:0}
  .nav a{padding:12px 0;border-bottom:1px solid var(--c-dividerDecorative);min-height:48px;display:flex;align-items:center}
}
/* open voeg: bracket at a content start (source vector, non-scaling stroke) */
.voeg{position:relative;padding-left:28px} .voeg::before{content:"";position:absolute;left:0;top:0;bottom:0;width:14px;border:2px solid var(--c-ink);border-right:0}
/* hero */
.hero{padding:80px 0 48px} .hero-grid{display:grid;grid-template-columns:1.1fr 1fr;gap:48px;align-items:center} @media(max-width:900px){.hero-grid{grid-template-columns:1fr}}
h1{font:var(--c-type-heroDesktop-weight) var(--c-type-heroDesktop-size)/var(--c-type-heroDesktop-line) var(--c-type-heroDesktop-family);margin:0 0 16px;letter-spacing:-.01em}
@media(max-width:720px){h1{font-size:var(--c-type-heroMobile-size);line-height:var(--c-type-heroMobile-line)}}
h2{font:var(--c-type-section-weight) var(--c-type-section-size)/var(--c-type-section-line) var(--c-type-section-family);margin:0 0 16px}
h3{font:var(--c-type-subheading-weight) var(--c-type-subheading-size)/var(--c-type-subheading-line) var(--c-type-subheading-family);margin:0 0 8px}
.sub{color:var(--c-textSecondary);margin:0 0 24px;max-width:60ch}
.btns{display:flex;gap:16px;flex-wrap:wrap;margin:0 0 16px}
.btn{display:inline-flex;align-items:center;min-height:48px;padding:12px 24px;border-radius:var(--c-radius);text-decoration:none;font:var(--c-type-button-weight) var(--c-type-button-size)/var(--c-type-button-line) var(--c-type-button-family);border:1px solid var(--c-ink);background:var(--c-ink);color:#fff}
.btn:hover{background:var(--c-action-hover)} .btn:active{background:var(--c-action-pressed)}
.btn.secondary{background:var(--c-surface);color:var(--c-ink)} .btn.secondary:hover{background:var(--c-tint)}
.btn[aria-disabled=true]{opacity:.5;cursor:not-allowed}
.helper{font:var(--c-type-helper-weight) var(--c-type-helper-size)/var(--c-type-helper-line) var(--c-type-helper-family);color:var(--c-textSecondary)}
img.full{width:100%;height:auto;display:block;background:var(--c-surface);border:1px solid var(--c-dividerDecorative)}
figure{margin:0} figcaption{font:400 14px/21px Manrope;color:var(--c-textSecondary);margin-top:8px}
/* full open voeg on core images (T-Q22, QA-12): site/logo/open-voeg.svg (v1.1 handover)
   is a 640x480 box with a full-height left bracket plus a top-right and a bottom-right
   corner — path `M36 16 H16 V464 H36 M604 16 H624 V36 M624 444 V464 H604`, stroke
   var(--c-ink), 2px. .voeg (above) only ever reused the left-bracket half of that, on
   headings; this reproduces the whole thing as a frame around the <img> only (never the
   <figcaption> — see the markup, the wrapper sits inside <figure>, around just the
   image), at the SVG's own inset (16 units) and arm length (20 units) rounded to the
   nearest values already in this file's spacing scale (16, 24) rather than computed per
   image size — that is the "scaled sensibly" the finding asked for, not a literal
   640x480 stretch. The image boxes this frames vary in rendered size (grid column width,
   responsive scaling), so fixed px arms keep the mark a consistent size regardless,
   rather than growing or shrinking with whatever the image happens to render at. Marks
   are 2px CSS borders (so the line stays a literal 2px regardless of the image's
   rendered size, stronger than the source's vector-effect:non-scaling-stroke) and are
   decorative: built from aria-hidden elements, nothing here is announced to a screen
   reader, and the "concept" wording stays in <figcaption> as it already was.
   Do not apply this to an image whose own artwork already carries the voeg and a code
   chip baked in (B05: the source raster already draws the left bracket, both right
   corners and its own "C-01 / v0.1" chip) — framing it again doubles the marks and
   shows two status chips side by side. It belongs only on artwork that has no voeg of
   its own, e.g. the B01 hero. */
.voeg-frame{position:relative}
.voeg-frame::before{content:"";position:absolute;left:16px;top:16px;bottom:16px;width:24px;border:2px solid var(--c-ink);border-right:0;pointer-events:none}
.voeg-frame .voeg-corner{position:absolute;width:24px;height:24px;pointer-events:none}
.voeg-frame .voeg-corner-tr{top:16px;right:16px;border-top:2px solid var(--c-ink);border-right:2px solid var(--c-ink)}
.voeg-frame .voeg-corner-br{bottom:16px;right:16px;border-bottom:2px solid var(--c-ink);border-right:2px solid var(--c-ink)}
/* Status field: the codevlak style already used for model codes (.label), but the
   model/version themselves wait on F2 (which model this is isn't confirmed), so this
   is deliberately status-only text ("CONCEPT") and nothing else — do not add a code or
   version here until F2 is answered. */
.voeg-frame .voeg-status{position:absolute;top:16px;left:48px;margin:0}
/* sections */
section{padding:48px 0} section.alt{background:var(--c-surface);border-top:1px solid var(--c-dividerDecorative);border-bottom:1px solid var(--c-dividerDecorative)}
.grid2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:32px} .grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px} @media(max-width:900px){.grid2,.grid3{grid-template-columns:minmax(0,1fr)}}
.panel{background:var(--c-surface);border:1px solid var(--c-dividerDecorative);padding:24px;border-radius:0}
.code{font:500 16px/24px "IBM Plex Mono",monospace;background:var(--c-accent);color:var(--c-ink);padding:0 6px;display:inline-block}
.measure{font:400 var(--c-type-measure-size)/var(--c-type-measure-line) "IBM Plex Mono",monospace}
.label{display:inline-block;font:500 14px/20px "IBM Plex Mono",monospace;background:var(--c-accent);padding:2px 8px;margin-bottom:8px}
.steps{counter-reset:s;list-style:none;padding:0;margin:0;display:grid;gap:16px} .steps li{position:relative;padding-left:56px;min-height:48px} .steps li::before{counter-increment:s;content:counter(s);position:absolute;left:0;top:0;width:40px;height:40px;border:1px solid var(--c-ink);display:grid;place-items:center;font:500 16px "IBM Plex Mono",monospace}
.roles{font-size:16px;color:var(--c-textSecondary)}
table{width:100%;border-collapse:collapse;font:var(--c-type-table-weight) var(--c-type-table-size)/var(--c-type-table-line) var(--c-type-table-family)} th,td{text-align:left;padding:8px 12px;border-bottom:1px solid var(--c-dividerDecorative);vertical-align:top} th{font-family:Manrope;font-weight:600}
/* horizontally-scrollable table wrapper (T-Q30/T-Q33, QA-04): a table cell holding an
   unbreakable token (a bare domain, e.g. fonts.googleapis.com) can't shrink below that
   token's width, so table{width:100%} alone still overflows a narrow viewport. Scroll the
   table itself, not the page — no overflow-x:hidden on <body>/<main>, content stays reachable
   for a mouse or trackpad, and tabindex+role=region on the wrapper keep it keyboard-reachable. */
.table-scroll{overflow-x:auto}
.table-scroll table{min-width:520px}
.table-scroll:focus-visible{outline:3px solid var(--c-ink);outline-offset:-3px}
details{border-top:1px solid var(--c-dividerDecorative);padding:12px 0} details summary{cursor:pointer;font-weight:600;list-style:none;display:flex;justify-content:space-between;min-height:48px;align-items:center} details summary::after{content:"+";font-family:"IBM Plex Mono"} details[open] summary::after{content:"–"}
.note{background:var(--c-info-bg);color:var(--c-info);border:1px solid var(--c-info);padding:12px 16px;border-radius:var(--c-radius);font-size:16px}
.warn{background:var(--c-warning-bg);color:var(--c-warning);border:1px solid var(--c-warning);padding:12px 16px;border-radius:var(--c-radius);font-size:16px}
/* mini configurator on the homepage (first interaction) */
.mini{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:16px 0} .mini label{display:block;font:600 16px/24px Manrope} .mini input{width:100%;min-height:48px;border:1px solid var(--c-controlBorder);border-radius:var(--c-radius);padding:8px 12px;font:400 20px/28px "IBM Plex Mono",monospace;background:#fff;color:var(--c-ink)}
/* mobile mini configurator (QA-02, T-Q05): three columns at 320–390px leave each
   number input ~80px wide, clipping the digits the field is asking for; stack
   the fields instead so the label and full value stay readable. */
@media(max-width:720px){.mini{grid-template-columns:1fr;gap:12px}}
.mini-out{font:400 20px/28px "IBM Plex Mono",monospace;margin:8px 0 16px}
/* mini form field errors (T-Q20, QA-01/QA-13): an invalid field is marked on the
   input itself and the message is tied to it with aria-describedby, same rule as
   the wizard's own size fields (site/ontwerpen/wizard.html). */
.mini input[aria-invalid=true]{border-color:var(--c-error);background:var(--c-error-bg)}
.mini .err{margin:6px 0 0;font:var(--c-type-helper-weight) var(--c-type-helper-size)/var(--c-type-helper-line) var(--c-type-helper-family);color:var(--c-error)}
/* footer */
.site-footer{background:var(--c-ink);color:#fff;padding:48px 0;margin-top:48px} .site-footer a{color:#fff} .site-footer .cols{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);gap:32px} .site-footer .cols p{overflow-wrap:anywhere} @media(max-width:900px){.site-footer .cols{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}} .site-footer .logo img{height:32px;filter:none}
.site-footer small{display:block;margin-top:24px;color:#C8D0CC}
/* legal footer row (T-Q09, QA-04/QA-17): contact/voorwaarden/privacy/cookies, the four
   service pages, linked from every page's footer rather than added to the main nav. No
   new color: reuses the identity's own divider token, same as .panel/.wrap borders. */
.site-footer .legalnav{margin:24px 0 0;padding-top:24px;border-top:1px solid var(--c-dividerDecorative);font-size:14px}
.wizard-frame{width:100%;height:1100px;border:1px solid var(--c-dividerDecorative);background:#fff}
/* mobile wizard frame (QA-02, T-Q05): a fixed 1100px iframe either crops the
   wizard or leaves a large empty band below it on a phone, and it is the wrong
   fix to force scrolling inside a small nested box on a touch screen. The
   frame is same-origin (ontwerpen/wizard.html on the same host), so the inline
   script below measures the embedded document and sets --wiz-h to match it,
   with this vh-based value only as the fallback before that measurement lands
   and if it ever cannot run. */
@media(max-width:720px){.wizard-frame{height:var(--wiz-h,80vh);min-height:520px}}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
