/* ==========================================================================
   BLUE BOARD — מערכת לוחות איטום
   Accessible (ת"י 5568 / WCAG 2.2 AA) RTL Hebrew stylesheet
   ========================================================================== */

/* ------------------------------------------------- self-hosted webfont
   Assistant (SIL OFL 1.1) — served locally, no third-party requests.     */
@font-face {
  font-family: "Assistant";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/assistant-hebrew.woff2") format("woff2");
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
@font-face {
  font-family: "Assistant";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/assistant-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;
}

/* --------------------------------------------------------------- tokens */
:root {
  --brand:        #054596;   /* 10.0:1 on white */
  --brand-dark:   #033068;
  --brand-deep:   #04203f;
  --brand-tint:   #eef3fb;
  --brand-tint-2: #dbe6f7;

  --core:         #2ba6e0;   /* XPS core cyan — decorative only, never text */

  /* Text tokens. Ratios below are the worst case across the three surfaces
     these sit on (#fff, --surface-2, --surface-3). All clear 7:1, i.e. AAA
     (1.4.6) rather than only the AA 4.5:1 the standard requires — secondary
     text carries most of the spec detail, so the extra headroom is worth the
     small loss of contrast hierarchy. */
  --core-ink:     #095377;   /* 7.2:1 — eyebrow / accent text */

  --ink:          #16202c;   /* 14.9:1 — body */
  --ink-2:        #40506a;   /*  7.4:1 — secondary paragraphs */
  --ink-3:        #444e5f;   /*  7.2:1 — spec keys, hints, captions */

  --line:         #dcdde0;   /* decorative dividers / card edges */
  --line-strong:  #83868c;   /* 3.6:1 on white — borders of inputs, buttons and
                                other UI components (WCAG 1.4.11 Non-text Contrast) */

  /* Surfaces are neutral greys, not blue-tinted. Blue is an accent here —
     buttons, icons, links, rules — never a page or band background. */
  --surface:      #ffffff;
  --surface-2:    #f4f5f6;   /* alternating bands */
  --surface-3:    #e9eaec;   /* cards, deeper band */

  --focus:        #b8340a;   /* high-contrast focus ring on both themes */

  --r-s: 6px;
  --r-m: 12px;
  --r-l: 20px;

  --shadow-s: 0 1px 2px rgba(4, 32, 63, .06), 0 2px 8px rgba(4, 32, 63, .05);
  --shadow-m: 0 2px 6px rgba(4, 32, 63, .07), 0 12px 28px rgba(4, 32, 63, .09);

  --wrap: 1240px;
  --gut: clamp(1rem, 4vw, 2.5rem);

  --step-0: clamp(1rem, .96rem + .2vw, 1.125rem);
  --step-1: clamp(1.15rem, 1.08rem + .35vw, 1.4rem);
  --step-2: clamp(1.4rem, 1.25rem + .7vw, 1.9rem);
  --step-3: clamp(1.7rem, 1.45rem + 1.2vw, 2.6rem);
  --step-4: clamp(2.1rem, 1.6rem + 2.3vw, 3.7rem);

  --ff: "Assistant", "Rubik", "Heebo", "Segoe UI", system-ui, -apple-system, "Arial Hebrew", Arial, sans-serif;

  --dur: .28s;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6.5rem;
}

body {
  margin: 0;
  font-family: var(--ff);
  font-size: var(--step-0);
  line-height: 1.7;
  color: var(--ink);
  background: var(--surface);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
img { background-color: var(--surface-2); }

h1, h2, h3, h4 { line-height: 1.22; margin: 0 0 .5em; font-weight: 800; letter-spacing: -.01em; }
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }
p  { margin: 0 0 1.1em; max-width: 68ch; }
ul, ol { margin: 0 0 1.1em; padding-inline-start: 1.4em; }
li { margin-bottom: .4em; }

a { color: var(--brand); text-underline-offset: .22em; text-decoration-thickness: .08em; }
a:hover { color: var(--brand-dark); text-decoration-thickness: .14em; }

strong, b { font-weight: 800; }
abbr[title] { text-decoration: underline dotted; cursor: help; }

/* ------------------------------------------------------------- focus ring
   WCAG 2.2 — 2.4.11 Focus Not Obscured / 2.4.13 Focus Appearance          */
:focus { outline: none; }
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: 3px;
}
/* Keyboard users get a solid ring even over photography */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px #fff, 0 0 0 9px var(--focus);
}

/* --------------------------------------------------------- helper classes */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut); }

.visually-hidden:not(:focus):not(:active) {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* The toolbar launcher is fixed and sits after </footer>, which made it the
   45th and last tab stop — 44 Tab presses away for the users most likely to
   want it. A skip-link entry puts it near the front of the tab order instead.
   Preferred over a key combination: nothing to memorise, it announces itself,
   and it avoids SC 2.1.4, which attaches obligations to character shortcuts. */
/* Unfocused, each link is clipped to a 1px box rather than parked at
   top:-100px. Parking them left three full-size boxes stacked at identical
   coordinates: they obscured one another, which axe reported as a real
   target-size failure (2.5.8) on the second link, and their phantom geometry
   also made 79 elements indeterminate for the contrast check. Clipping gives
   them no area to overlap with while keeping them focusable and in the tab
   order. */
.skip-links a,
.skip-links button {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
}
.skip-links a:focus,
.skip-links button:focus {
  inset-inline-start: 1rem;
  top: 0;
  z-index: 2000;
  width: auto;
  height: auto;
  padding: .9rem 1.5rem;
  overflow: visible;
  clip-path: none;
  border-radius: 0 0 var(--r-s) var(--r-s);
}

/* Skip-link landing zones. tabindex="-1" makes them focusable programmatically
   without adding them to the tab order, so activating a skip link moves real
   focus rather than only the scroll position. Draw the ring inside the box so
   a whole-page region does not gain a 3px halo. */
main[tabindex="-1"]:focus-visible,
nav[tabindex="-1"]:focus-visible,
section[tabindex="-1"]:focus-visible,
.a11y-panel:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: -3px;
  box-shadow: none;
}
/* The panel keeps its own border, so restore that alongside the inset ring. */
.a11y-panel:focus-visible { border-color: var(--brand); }

.eyebrow {
  display: inline-block;
  font-size: .82rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--core-ink);
  margin-bottom: .75rem;
}
.eyebrow::before {
  content: "";
  display: inline-block;
  width: 1.6rem; height: 3px;
  background: var(--core);
  vertical-align: .28em;
  margin-inline-end: .6rem;
}

.lede { font-size: var(--step-1); color: var(--ink-2); max-width: 62ch; }
.muted { color: var(--ink-3); }
/* Latin runs inside Hebrew text. `isolate` (not inline-block) keeps the run
   from reordering neighbouring Hebrew while still wrapping as normal inline
   content — inline-block would strand the preceding Hebrew prefix on its own line. */
.en { unicode-bidi: isolate; direction: ltr; }

/* Numeric/comparison expressions such as “< 0.8%” or “> 400 kPa”. The bidi
   algorithm mirrors < and > inside an RTL run, which flips their meaning, so
   these are isolated LTR and kept on one line. */
.num { unicode-bidi: isolate; direction: ltr; white-space: nowrap; }

.nowrap { white-space: nowrap; }

section { scroll-margin-top: 6.5rem; }
.band { padding-block: clamp(3.5rem, 8vw, 6.5rem); }
.band--tint { background: var(--surface-2); }

/* --brand and --brand-deep used to fill these two bands edge to edge, which
   put large flat areas of blue through the whole page. They are neutral now;
   blue survives as accent only. Text reverts to the normal ink tokens, all of
   which clear AAA on these greys (13.7:1 body, 7.0:1 muted). */
.band--brand { background: var(--surface-3); color: var(--ink); }
.band--brand h2, .band--brand h3 { color: var(--ink); }
.band--brand .lede, .band--brand p { color: var(--ink-2); }
.band--brand .eyebrow { color: var(--core-ink); }

.band--deep { background: var(--surface-2); color: var(--ink); }
.band--deep h2, .band--deep h3 { color: var(--ink); }
.band--deep p { color: var(--ink-2); }
.band--deep .eyebrow { color: var(--core-ink); }

.section-head { max-width: 68ch; margin-bottom: clamp(2rem, 4vw, 3.25rem); }

/* ------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  min-height: 48px;              /* > 24px target — WCAG 2.5.8 */
  padding: .8rem 1.7rem;
  border: 2px solid transparent;
  border-radius: 999px;
  font: inherit;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur), color var(--dur), border-color var(--dur), transform var(--dur);
}
.btn--primary { background: var(--brand); color: #fff; border-color: var(--brand); }
.btn--primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }
.btn--ghost { background: transparent; color: var(--brand); border-color: var(--line-strong); }
.btn--ghost:hover { background: var(--brand-tint); border-color: var(--brand); color: var(--brand-dark); }
/* Named for the old dark hero. Now blue on the light panel: solid for the
   primary action, outlined for the secondary. */
.btn--on-dark { background: var(--brand); color: #fff; border-color: var(--brand); }          /* 9.1:1 */
.btn--on-dark:hover { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }
.btn--outline-light { background: transparent; color: var(--brand); border-color: var(--brand); }
.btn--outline-light:hover { background: var(--brand); color: #fff; border-color: var(--brand); }
.btn:active { transform: translateY(1px); }

.btn-row { display: flex; flex-wrap: wrap; gap: .85rem; margin-top: 1.75rem; }

/* -------------------------------------------------------------- header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 900;
  /* Opaque, not rgba(255,255,255,.96). The sticky header scrolls over
     photography, so a translucent background makes the nav's effective
     backdrop depend on the image behind it — indeterminate to a checker and,
     in the worst case, a real contrast risk. The 4% was imperceptible. */
  background: #fff;
  border-bottom: 1px solid var(--line);
}
.header-inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 74px;
  padding-block: .9rem;   /* the wordmark was sitting hard against both edges */
}
.brand-link { display: flex; align-items: center; flex: 0 0 auto; text-decoration: none; }
.brand-link img { width: clamp(122px, 15vw, 160px); background: none; }

.primary-nav { margin-inline-start: auto; }
.primary-nav > ul {
  display: flex;
  align-items: center;
  gap: .15rem;
  list-style: none;
  margin: 0; padding: 0;
}
.primary-nav a {
  display: block;
  padding: .6rem .85rem;
  border-radius: var(--r-s);
  color: var(--ink);
  font-weight: 700;
  font-size: .98rem;
  text-decoration: none;
}
.primary-nav a:hover { background: var(--brand-tint); color: var(--brand-dark); text-decoration: underline; }
.primary-nav a[aria-current="page"],
.primary-nav a.is-active {
  color: var(--brand);
  box-shadow: inset 0 -3px 0 var(--brand);
}
.header-cta { flex: 0 0 auto; }

.nav-toggle, .a11y-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  min-width: 48px; min-height: 48px;
  padding: 0 .7rem;
  background: transparent;
  border: 2px solid var(--line-strong);
  border-radius: var(--r-s);
  color: var(--brand);
  font: inherit; font-weight: 700;
  cursor: pointer;
}
.nav-toggle:hover, .a11y-toggle:hover { background: var(--brand-tint); border-color: var(--brand); }
.nav-toggle { display: none; }
.nav-toggle svg, .a11y-toggle svg { width: 24px; height: 24px; fill: currentColor; }

@media (max-width: 1080px) {
  .nav-toggle { display: inline-flex; margin-inline-start: auto; }
  .header-cta { display: none; }
  .primary-nav {
    /* absolute, not fixed: .site-header is position:sticky and so already
       establishes a containing block, giving the same result — and it keeps
       the drawer working when the header carries a filter (see the greyscale
       rule, where a filtered ancestor re-anchors fixed descendants). */
    position: absolute;
    /* top:100% rather than a hard-coded 74px — the header grew when the logo
       gained breathing room, and a fixed offset would have left a gap. */
    inset: 100% 0 auto 0;
    margin: 0;
    background: #fff;
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-m);
    max-height: calc(100dvh - 100%);
    overflow-y: auto;
    padding: 1rem var(--gut) 2rem;
  }
  .primary-nav[hidden] { display: none; }
  .primary-nav > ul { flex-direction: column; align-items: stretch; gap: .2rem; }
  .primary-nav a { padding: .95rem .8rem; font-size: 1.05rem; border-bottom: 1px solid var(--line); border-radius: 0; }
  .primary-nav a[aria-current="page"], .primary-nav a.is-active { box-shadow: inset 3px 0 0 var(--brand); background: var(--brand-tint); }
}

/* ---------------------------------------------------------------- hero */
/* Taller banner. Column layout so the stat strip is pushed to the foot by the
   copy panel's auto margin, whatever the height works out to. The dvh unit
   keeps mobile browser chrome from cropping it, and the min() cap stops short
   viewports from turning the banner into a full-screen takeover. */
.hero {
  position: relative;
  background: var(--surface-2);
  color: var(--ink);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* dvh rather than vh so mobile browser chrome collapsing does not resize the
     banner mid-scroll. Capped in px so it does not become absurd on a tall
     desktop monitor. */
  min-height: min(92dvh, 900px);
}
.hero__media { position: absolute; inset: 0; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* A flat white veil over the photograph, so the hero reads as part of the
   light palette rather than a full-strength image behind a floating card.
   White rather than black: it only raises the luminance the dark copy sits
   on, so it can never work against the panel's contrast. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .34);
  pointer-events: none;
}

/* ---- video hero ----
   The video IS the banner. At rest its still fills the hero behind the copy
   panel, with a play control in the open half. Pressing play hides the copy,
   the stats and the still, and the player takes the banner at a true 16:9 —
   no letterbox, and no text left sitting over moving video. */
.hero--video .hero__media::after { background: rgba(255, 255, 255, .2); }
.hero--video .hero__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
}
.hero--video .hero__inner { margin-inline: 0; max-width: none; }
.hero__play-slot { display: grid; place-items: center; }

/* A real button with a visible label; the accessible name begins with that
   label (WCAG 2.5.3), so a voice-control user can say what they see. */
.hero-play {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: .8rem;
  padding: .5rem;
  border: 0;
  border-radius: 1.25rem;
  background: none;
  font: inherit;
  cursor: pointer;
}
.hero-play__icon {
  display: grid;
  place-items: center;
  width: clamp(4.5rem, 9vw, 6.5rem);
  height: clamp(4.5rem, 9vw, 6.5rem);
  border-radius: 50%;
  background: rgba(255, 255, 255, .95);
  box-shadow: 0 10px 30px rgba(4, 32, 63, .28);
  transition: transform .15s ease;
}
/* the triangle's path is already optically centred in its 24-unit box */
.hero-play__icon svg { width: 44%; height: 44%; fill: var(--brand); }
.hero-play__label {
  padding: .35rem 1rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, .95);
  color: var(--ink);
  font-weight: 800;
  font-size: 1.02rem;
}
.hero-play:hover .hero-play__icon,
.hero-play:focus-visible .hero-play__icon { transform: scale(1.06); }
.hero-play:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }

/* ---- playing ---- */
.hero--playing { min-height: 0; }
.hero--playing .hero__media,
.hero--playing .hero__play-slot,
.hero--playing .hero__inner > :not(h1),
.hero--playing .hero__strip { display: none; }
/* The text is hidden from sight, not from assistive technology: the page's
   only h1 stays in the accessibility tree (visually hidden, the same recipe
   as .visually-hidden) so heading navigation still finds it while the video
   plays. Everything focusable in the hero is display:none above, so nothing
   invisible can take focus. */
.hero--playing .hero__layout {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.hero__player {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 86dvh;
  border: 0;
  background: #000;
}
/* Below the player, not on it: over the video it would sit on top of
   YouTube's own title bar and controls. */
.hero__close {
  align-self: center;
  margin-block: .9rem;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 44px;
  padding: .55rem 1.25rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 800;
  cursor: pointer;
}
.hero__close[hidden] { display: none; }
.hero__close svg {
  width: 1.05rem;
  height: 1.05rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
}
.hero__close:hover { border-color: var(--brand); color: var(--brand); }
.hero__close:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) { .hero-play__icon { transition: none; } }

@media (max-width: 60em) {
  .hero--video .hero__layout { grid-template-columns: 1fr; }
  /* play first on small screens, so it sits on the image above the copy */
  .hero__play-slot { order: -1; padding-top: 1rem; }
}

/* The backdrop for the copy is a panel on .hero__inner, NOT a wash across the
   whole image.

   Every wash-based attempt here failed for the same reason: the guarantee has
   to hold wherever the copy actually sits, and that moves. Gradient angles are
   not mirrored by `direction`, so an RTL layout flips which end is solid; and
   .hero__inner carries .wrap, whose margin-inline:auto centres the column, so
   its start position shifts with the viewport (~22% of the hero at 1280px,
   ~13% at 960px). Any fixed percentage is wrong at some width, and a wash
   light enough to keep the photograph attractive was not dark enough to carry
   dark text over it.

   Putting the panel on the column removes the geometry problem entirely: it is
   the same element the text lives in, so it tracks the text at every viewport
   by construction. White at .80 over the worst case the photo can supply (a
   pure black pixel) still gives 10.2:1 for the heading and 5.1:1 for the lede —
   AA throughout. .76 is the floor; below that the lede drops under 4.5:1.

   No wash over the image at all — the photograph runs at full strength. That
   is safe precisely because the guarantee lives on the panel: the worst case
   behind it is still a pure black or pure white pixel either way, so removing
   the knock-back changes the contrast maths not at all. */

/* .hero__layout is the page container; the panel sits at its inline-start
   edge, which in RTL is the right. margin-inline-start:0 overrides the auto
   margins .wrap would otherwise use to centre it. */
.hero__layout { position: relative; }
.hero__inner {
  position: relative;
  max-width: 46rem;
  margin-block: clamp(3rem, 8vw, 5.5rem);
  margin-inline-start: 0;
  margin-inline-end: auto;
  padding: clamp(1.75rem, 4vw, 3rem) clamp(1.5rem, 4vw, 3rem);
  background: rgba(255, 255, 255, .80);
  border-radius: var(--r-l);
  box-shadow: var(--shadow-m);
}

.hero h1 { color: var(--ink); margin-bottom: .45em; text-wrap: balance; }
.hero .lede { color: var(--ink-2); font-size: clamp(1.1rem, 1rem + .6vw, 1.45rem); }
.hero .eyebrow { color: var(--core-ink); }
.hero .eyebrow::before { background: var(--brand); }

/* Headline figures as a full-width strip pinned to the foot of the banner,
   rather than a fourth block inside the copy panel. Four fixed columns — as a
   flex row they wrapped, dropping one figure onto a line of its own. */
.hero__strip {
  position: relative;
  margin-top: auto;
  background: var(--surface);
  border-top: 1px solid var(--line);
}
.hero-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1rem, 3vw, 2.5rem);
  /* margin-block only — a blanket `margin: 0` here wiped out the
     margin-inline:auto this element inherits from .wrap, which left the whole
     strip flush to one edge instead of centred in the page container. */
  margin-block: 0;
  padding-block: clamp(1rem, 2.5vw, 1.5rem);
}
.hero-stats dt { font-size: .84rem; color: var(--ink-3); font-weight: 700; letter-spacing: .04em; }
.hero-stats dd { margin: .15rem 0 0; font-size: clamp(1.25rem, 2.4vw, 1.9rem); font-weight: 800; color: var(--brand); }

@media (max-width: 48em) {
  .hero-stats { grid-template-columns: repeat(2, 1fr); row-gap: 1rem; }
}

/* ---------------------------------------------------------- badge strip
   Was a full-width slab of --brand. Now white with hairline rules, so the
   blue reads only in the icons and the page stays neutral. Fixed at three
   across so six badges make two even rows — auto-fit was leaving one
   stranded on a row of its own. */
.badges { background: var(--surface); color: var(--ink); border-block: 1px solid var(--line); }
.badges ul {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  list-style: none; margin: 0; padding: 0;
  background: var(--line);
}
.badges li {
  display: flex; align-items: center; gap: .9rem;
  margin: 0;
  padding: 1.5rem clamp(1rem, 2vw, 1.6rem);
  background: var(--surface);
}
@media (max-width: 60em) { .badges ul { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 36em) { .badges ul { grid-template-columns: 1fr; } }

.badges svg { flex: 0 0 auto; width: 34px; height: 34px; fill: none; stroke: var(--brand); stroke-width: 1.7; }
/* `.badges span` also matched the wrapper span, so the bold label inherited the
   muted colour. Target the label and the description separately. */
.badges li > span { display: block; }
.badges b { display: block; color: var(--ink); font-size: 1.02rem; line-height: 1.35; }  /* 16.4:1 */
.badges b + span { font-size: .86rem; color: var(--ink-3); line-height: 1.4; }           /*  8.4:1 */

/* ---------------------------------------------------------------- grids
   Fixed column counts rather than auto-fit. auto-fit packs as many as will
   fit, which kept leaving a single card stranded on a row of its own —
   4+2 in the gallery, 6+2 in the groove diagrams, 3+1 in the shower trays.
   Explicit counts step down cleanly at each breakpoint instead. */
.grid { display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 75em) {
  .grid--4 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 60em) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 40em) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
}

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
}
.split--media-start > .split__media { order: -1; }

.split__media img {
  width: 100%;
  border-radius: var(--r-m);
  box-shadow: var(--shadow-m);
}
.split__media--plain img { box-shadow: none; background: none; }

/* ---------------------------------------------------------------- cards */
.card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  overflow: hidden;
  transition: border-color var(--dur), box-shadow var(--dur), transform var(--dur);
}
.card:hover, .card:focus-within { border-color: var(--brand); box-shadow: var(--shadow-m); }
.card__media { background: var(--surface-3); aspect-ratio: 4 / 3; }
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card__media--contain { background: var(--surface-2); }
.card__media--contain img { object-fit: contain; padding: 1.1rem; }
.card__body { padding: 1.35rem 1.4rem 1.5rem; flex: 1; display: flex; flex-direction: column; }
.card__body h3 { font-size: var(--step-1); margin-bottom: .4rem; }
.card__body p { font-size: .96rem; color: var(--ink-2); margin-bottom: 1rem; }
.card__body p:last-child { margin-bottom: 0; }
.card__link { margin-top: auto; font-weight: 800; text-decoration: none; }
.card__link::after { content: " ←"; }
.card__link:hover { text-decoration: underline; }
/* whole-card click target that keeps a single tab stop */
.card__link::before { content: ""; position: absolute; inset: 0; }
.card { position: relative; }

.spec-list { list-style: none; margin: 0; padding: 0; font-size: .93rem; }
.spec-list li {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .55rem 0;
  border-bottom: 1px solid var(--line);
  margin: 0;
}
.spec-list li:last-child { border-bottom: 0; }
.spec-list dt, .spec-list .k { color: var(--ink-3); }
.spec-list .v { font-weight: 700; text-align: start; }

/* ---------------------------------------------------------- feature list */
.feature-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.6rem; }
.feature-list > li { display: flex; gap: 1.1rem; margin: 0; }
.feature-list .ico {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 46px; height: 46px;
  background: var(--brand-tint);
  border-radius: 50%;
  color: var(--brand);
}
.feature-list .ico svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.feature-list h3 { font-size: 1.08rem; margin-bottom: .2rem; }
.feature-list p { font-size: .96rem; color: var(--ink-2); margin: 0; }

/* --------------------------------------------------------------- layers */
.layers { list-style: none; margin: 1.5rem 0 0; padding: 0; counter-reset: l; }
.layers li {
  display: flex; align-items: center; gap: 1rem;
  padding: .95rem 1.1rem;
  margin: 0 0 .6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-inline-start: 5px solid var(--brand);
  border-radius: var(--r-s);
  font-weight: 700;
}
.layers li:nth-child(4) { border-inline-start-color: var(--core); }
.layers .n {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 30px; height: 30px;
  background: var(--brand-tint); color: var(--brand-dark);
  border-radius: 50%;
  font-size: .85rem; font-weight: 800;
}
.layers small { display: block; font-weight: 500; color: var(--ink-3); font-size: .87rem; line-height: 1.4; }

/* --------------------------------------------------------------- tables */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface);
}
.table-wrap:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
table { width: 100%; border-collapse: collapse; font-size: .95rem; min-width: 34rem; }

/* The 34rem floor exists so the wide five-column data sheet stays legible and
   scrolls instead of crushing. Applied to the narrow two-column size tables —
   which sit three-up in a ~360px grid column — it forced a scrollbar on every
   viewport and pushed half the cells out of view. Those tables opt out. */
.table-wrap--compact table { min-width: 0; }
caption {
  text-align: start;
  padding: 1.1rem 1.25rem;
  font-weight: 800;
  font-size: var(--step-1);
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}
caption .muted { display: block; font-size: .9rem; font-weight: 500; margin-top: .2rem; }
th, td { padding: .8rem 1.1rem; text-align: start; border-bottom: 1px solid var(--line); }
thead th { background: var(--brand); color: #fff; font-weight: 700; border-bottom: 0; }
tbody th { font-weight: 700; background: var(--surface-2); }
tbody tr:last-child th, tbody tr:last-child td { border-bottom: 0; }
tbody tr:nth-child(even) td { background: var(--surface-2); }
tbody tr:nth-child(even) th { background: var(--surface-3); }
td .ok { color: #17603a; font-weight: 800; }

/* ------------------------------------------------------------- accordion */
.acc { border: 1px solid var(--line); border-radius: var(--r-m); overflow: hidden; background: #fff; }
.acc + .acc { margin-top: .8rem; }
.acc > summary {
  display: flex; align-items: center; gap: .9rem;
  padding: 1.1rem 1.35rem;
  min-height: 48px;
  font-weight: 800; font-size: var(--step-1);
  cursor: pointer;
  list-style: none;
  background: var(--surface-2);
}
.acc > summary::-webkit-details-marker { display: none; }
.acc > summary::after {
  content: "";
  margin-inline-start: auto;
  width: 12px; height: 12px;
  border: 3px solid var(--brand);
  border-top: 0; border-inline-start: 0;
  transform: rotate(45deg);
  transition: transform var(--dur);
}
.acc[open] > summary::after { transform: rotate(-135deg); }
.acc > summary:hover { background: var(--brand-tint); }
.acc__body { padding: 1.4rem 1.35rem 1.6rem; }
.acc__body > :last-child { margin-bottom: 0; }

/* ------------------------------------------------------------ gallery */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: 1rem;
  list-style: none; margin: 0; padding: 0;
}
/* Explicit counts so each gallery fills its rows evenly instead of leaving a
   stray item on a row of its own: 6 applications as 3+3, 8 groove patterns
   and 4 drain positions as 4+4 and 4. */
.gallery--3 { grid-template-columns: repeat(3, 1fr); }
.gallery--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 60em) {
  .gallery--3, .gallery--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 40em) {
  .gallery--3, .gallery--4 { grid-template-columns: 1fr; }
}
.gallery li { margin: 0; }
.gallery figure { margin: 0; border-radius: var(--r-m); overflow: hidden; background: var(--surface-3); }
.gallery img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.gallery figcaption { padding: .85rem 1rem; font-size: .92rem; color: var(--ink-2); background: var(--surface); border: 1px solid var(--line); border-top: 0; }

/* --------------------------------------------------------------- certs */
/* ---------------------------------------------------------------- slideshow */

.slideshow { position: relative; }

.slideshow__viewport {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--r-l);
  background: var(--surface-3);
}

/* Slides are stacked and cross-faded rather than translated in a track.
   A sliding track has to know which way "next" is, and the answer flips
   under RTL — opacity has no direction, so nothing here depends on it. */
.slideshow__track {
  list-style: none;
  margin: 0;
  padding: 0;
  height: 100%;
}

/* Visible is the default and hiding is the override, so that with JS disabled
   — when nothing ever sets aria-hidden — the slides simply stack and the top
   one shows, instead of the viewport going blank. It also means slide 1 is
   painted on load rather than fading up from nothing. */
.slideshow__slide {
  position: absolute;
  inset: 0;
  margin: 0;
  /* Short and front-loaded. At a 2s interval a 400ms cross-fade is a fifth of
     the cycle, so the carousel reads as permanently mid-transition and a click
     feels like it lagged. 180ms is under the ~200ms that registers as delay. */
  transition: opacity .18s ease-out;
}
/* Hidden slides keep their box (so the viewport never collapses) but must not
   swallow clicks aimed at the visible one. Keyboard reachability is handled
   separately, by inert. */
.slideshow__slide[aria-hidden="true"] { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .slideshow__slide { transition: none; }
}

.slideshow__slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.slideshow__caption {
  /* The fade lives in the top padding and nowhere else (see background). */
  --caption-fade: clamp(1.5rem, 4vw, 2.5rem);
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  margin: 0;
  padding: var(--caption-fade) clamp(1rem, 3vw, 1.75rem) clamp(.9rem, 2vw, 1.25rem);
  color: #fff;
  font-weight: 700;
  font-size: clamp(.95rem, .9rem + .3vw, 1.15rem);
  /* Solid floor under the text, fading up: the caption sits over photography,
     so contrast cannot rely on the image. The fade is confined to the top
     padding, so every line of text sits on >=.72 black — white text 9:1 even
     over pure white pixels, at any width and any number of lines. A
     percentage stop (the old 45%) put the top of the text inside the fade on
     phones, where the padding is thinner: 4.5:1 there, a hair from failing. */
  background: linear-gradient(to top,
    rgba(0, 0, 0, .82) 0%,
    rgba(0, 0, 0, .72) calc(100% - var(--caption-fade)),
    rgba(0, 0, 0, 0) 100%);
}

.slideshow__controls {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-top: 1.1rem;
  flex-wrap: wrap;
}

.slideshow__nav,
.slideshow__play {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: .5rem .9rem;
  background: var(--surface);
  color: var(--brand);
  border: 2px solid var(--line-strong);
  border-radius: var(--r-s);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.slideshow__nav { padding: .5rem; }
.slideshow__nav svg { width: 1.35rem; height: 1.35rem; display: block; }
.slideshow__nav:hover,
.slideshow__play:hover { border-color: var(--brand); background: var(--surface-2); }

.slideshow__play { margin-inline-start: auto; font-size: .92rem; }

.slideshow__dots {
  display: flex;
  gap: .4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.slideshow__dots li { margin: 0; }
.slideshow__dots button {
  /* 2.75rem hit area around a 10px painted dot — target size without the dots
     themselves becoming heavy. */
  position: relative;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
/* ::before is the ring, always drawn. ::after is the fill that grows inside it
   while autoplay counts down, so the dot doubles as the progress indicator and
   the timing is visible rather than a surprise. */
.slideshow__dots button::before {
  content: "";
  width: .8rem;
  height: .8rem;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--line-strong);
}
.slideshow__dots button[aria-current="true"]::before { border-color: var(--brand); }
.slideshow__dots button::after {
  content: "";
  position: absolute;
  width: .8rem;
  height: .8rem;
  border-radius: 50%;
  background: var(--brand);
  /* Clipped away entirely when not current. Clipping rather than scaling means
     the dot always keeps its true size and circular edge — a scaled blob reads
     as a wobble, whereas this reads as a level rising. */
  clip-path: inset(100% 0 0 0);
}
/* Paused: the current dot is simply solid. */
.slideshow__dots button[aria-current="true"]::after { clip-path: inset(0 0 0 0); }
/* Playing: it fills bottom-to-top over exactly one slide interval. */
.slideshow__dots button.is-filling::after {
  animation: dotFill var(--slide-delay, 2s) linear forwards;
}
@keyframes dotFill {
  from { clip-path: inset(100% 0 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* Reduced motion still needs to show which dot is current — it just does not
   animate getting there. */
@media (prefers-reduced-motion: reduce) {
  .slideshow__dots button.is-filling::after { animation: none; clip-path: inset(0 0 0 0); }
}

@media (max-width: 40em) {
  .slideshow__play { margin-inline-start: 0; width: 100%; }
}

/* -------------------------------------------------------------- board tiles */

/* The flagship board as three gauge tiles. The thickness is the thing a buyer
   is choosing between, so it is the largest element in each tile and the rest
   hangs off it. */
.board-tiles__title {
  margin: clamp(2rem, 4vw, 2.75rem) 0 1.25rem;
  font-size: clamp(1.05rem, 1rem + .4vw, 1.3rem);
}
.board-tiles__title:first-of-type { margin-top: 0; }

/* Wide crop: the point of this shot is the run of board across the roof, so a
   letterbox keeps that and loses the empty sky. */
.board-shot {
  margin: 0 0 clamp(1.75rem, 3.5vw, 2.5rem);
  border-radius: var(--r-l);
  overflow: hidden;
  background: var(--surface-3);
}
.board-shot img {
  display: block;
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
}
@media (max-width: 48em) {
  .board-shot img { aspect-ratio: 3 / 2; }
}

.board-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(.85rem, 1.8vw, 1.4rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.board-tiles li {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: clamp(1.25rem, 2.6vw, 1.85rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 4px solid var(--brand);
  border-radius: var(--r-m);
}
/* The same render heads all three tiles — it is one board in three thicknesses,
   not three products, so a shared image is honest. alt="" on every copy: the
   thickness beneath it carries the meaning, and three identical descriptions
   would just be noise to a screen reader. */
.board-tiles__img {
  display: block;
  width: 100%;
  height: clamp(7rem, 14vw, 10rem);
  object-fit: contain;
  margin-bottom: 1rem;
}

.board-tiles__gauge {
  margin: 0 0 1rem;
  font-size: clamp(2rem, 1.4rem + 2.2vw, 3rem);
  font-weight: 800;
  line-height: 1;
  color: var(--brand);
}
.board-tiles__unit { font-size: .4em; font-weight: 700; color: var(--ink-2); }

.board-tiles dl { margin: 0; }
.board-tiles dl div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .55rem 0;
  border-top: 1px solid var(--line);
}
.board-tiles dt { margin: 0; font-size: .9rem; color: var(--ink-3); }
.board-tiles dd { margin: 0; font-weight: 800; color: var(--ink); }

.board-tiles__use {
  margin: 1rem 0 0;
  padding-top: .85rem;
  border-top: 1px solid var(--line);
  font-size: .92rem;
  color: var(--ink-2);
}

@media (max-width: 48em) { .board-tiles { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- standards */

/* The Israeli test certificate leads the section on its own, at a size the
   international factory approvals below it do not get — it is the only result
   measured on this product, by a third party, in this market. */
.standard-lead {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(1.25rem, 3vw, 2.25rem);
  align-items: start;
  padding: clamp(1.5rem, 3.5vw, 2.5rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-inline-start: 5px solid var(--brand);
  border-radius: var(--r-l);
  box-shadow: var(--shadow-s);
}
.standard-lead__icon { color: var(--brand); }
.standard-lead__icon svg { width: clamp(2.75rem, 6vw, 4rem); height: auto; display: block; }
/* The מת"י mark from the supplied PSD is a wide lockup (588x160), so it is
   sized by height and lets width follow — at 3.25–4.5rem tall it lands around
   190–265px wide, level with the heading beside it. Capped at the source's
   own 160px so it is never upscaled. */
.standard-lead__icon img {
  display: block;
  height: clamp(3.25rem, 6vw, 4.5rem);
  width: auto;
  max-height: 160px;
}
.standard-lead h3 { margin: 0 0 .6rem; font-size: clamp(1.15rem, 1rem + .6vw, 1.5rem); }
.standard-lead > div > p { margin: 0 0 1rem; }

.standard-meta {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 2.25rem;
  margin: 0 0 1rem;
  padding: 1rem 0 0;
  border-top: 1px solid var(--line);
}
.standard-meta div { display: flex; gap: .5rem; align-items: baseline; }
.standard-meta dt { font-size: .85rem; color: var(--ink-3); margin: 0; }
.standard-meta dd { margin: 0; font-weight: 800; color: var(--ink); }

/* The certificate forbids partial use and states it is not a תו תקן licence.
   That wording is a condition of quoting the result at all, so it is styled to
   stay legible rather than shrunk into disclaimer noise: 4.6:1 on --surface. */
.standard-note {
  margin: 0;
  font-size: .9rem;
  line-height: 1.65;
  color: var(--ink-3);
}

.standards-sub {
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 1.25rem;
  font-size: clamp(1.05rem, 1rem + .4vw, 1.3rem);
}

/* The seven SII tests read as a checklist, not a paragraph — a buyer scans
   for the one that matters to them. */
.test-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: .6rem 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.test-list li {
  position: relative;
  margin: 0;
  padding-inline-start: 1.9rem;
  color: var(--ink-2);
}
.test-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: .42em;
  width: .95rem;
  height: .5rem;
  border-inline-start: 2.5px solid var(--brand);
  border-bottom: 2.5px solid var(--brand);
  transform: rotate(-45deg);
}

.standards-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(.75rem, 1.6vw, 1.25rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.standards-grid li {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: .5rem;
  margin: 0;
  padding: clamp(1.1rem, 2.4vw, 1.6rem) .75rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
}
.standards-grid__icon { color: var(--brand); }
.standards-grid__icon svg { width: 2.25rem; height: 2.25rem; display: block; }
.standards-grid__name { font-weight: 800; color: var(--ink); }
.standards-grid__desc { font-size: .88rem; color: var(--ink-3); }

/* Mark tiles set the certification's name as the visual. Sized to stay legible
   at CodeMark's length without shrinking CE into a dot. */
.standards-grid--marks { grid-template-columns: repeat(5, 1fr); }
/* flex-start, not space-between: with the mark boxed to a fixed height, all
   ten logos then sit on the same line across a row, and a caption that wraps
   (REACH's) lengthens its own tile instead of shoving its logo upward. */
.standards-grid--marks li { justify-content: flex-start; gap: .85rem; }

/* Certification artwork, where it is supplied. The tile keeps the mark's name
   in text beneath it either way, so the meaning never depends on the image
   loading — and the name stays the accessible label, which is why the images
   carry alt="". Contained, not cropped: a certification mark distorted to fill
   a box is a defective mark. */
.standards-grid__logo {
  display: block;
  /* A common BOX, not a common height. Height alone let a wide wordmark
     (REACH, aspect 3.9) render four times the width of a square badge; fit
     into 10rem x 3.5rem, wide marks shrink and the wall balances. */
  width: 100%;
  max-width: 10rem;
  height: 3.5rem;
  margin-inline: auto;
  margin-bottom: .15rem;
  object-fit: contain;
  /* The global img rule paints a lazy-load placeholder behind every image.
     On a transparent mark that is a grey band the full width of the tile. */
  background: none;
}
.standards-grid__mark {
  font-size: clamp(1.05rem, .8rem + .7vw, 1.5rem);
  font-weight: 800;
  line-height: 1.1;
  color: var(--brand);
  letter-spacing: -.01em;
  overflow-wrap: anywhere;
}

@media (max-width: 75em) { .standards-grid--marks { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 40em) { .standards-grid--marks { grid-template-columns: repeat(2, 1fr); } }

.standards-foot {
  margin: clamp(1.75rem, 3.5vw, 2.5rem) 0 0;
  max-width: 62ch;
  color: var(--ink-2);
}

@media (max-width: 60em) { .standards-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 40em) {
  .standard-lead { grid-template-columns: 1fr; }
  .standards-grid { grid-template-columns: repeat(2, 1fr); }
}

.certs { display: flex; flex-wrap: wrap; gap: .7rem; list-style: none; margin: 0; padding: 0; }
.certs li {
  margin: 0;
  padding: .6rem 1.15rem;
  border: 2px solid var(--line-strong);
  border-radius: 999px;
  font-weight: 800;
  font-size: .95rem;
  color: var(--ink-2);
  background: #fff;
}
/* These were white-on-blue. On the neutral band that left white text on light
   grey — invisible. They inherit the default light-surface chip now. */
.band--brand .certs li { border-color: var(--line-strong); color: var(--ink-2); background: var(--surface); }

/* -------------------------------------------------------------- contact */
/* The white card the form sits on. Was an inline style; moved here so the
   background resolves for checkers that ignore custom properties in a
   style attribute. */
.contact-form {
  background: #fff;
  color: var(--ink);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  border-radius: var(--r-m);
}
.contact-form h3 { margin-top: 0; }

/* The form is a LIGHT card nested inside .band--deep, whose text rules are
   descendant selectors (`.band--deep h3`, `.band--deep p`) and therefore reach
   in here and beat `.muted` on specificity. Without these two lines the
   heading rendered white on white (1:1, invisible) and the helper paragraphs
   at 1.43:1.

   Worth recording how this was found: every token was correct measured against
   its intended surface, so a palette-level contrast check passed it. Only
   running axe-core against the live DOM — which reads computed style after the
   cascade — surfaced it. Component colours are declared here so the card does
   not depend on what the surrounding band happens to set. */
.contact-form h3 { color: var(--ink); }        /* 14.9:1 on the white card */
.contact-form p  { color: var(--ink-3); }      /*  7.2:1 */

.contact-grid { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li { display: flex; gap: .9rem; align-items: flex-start; margin-bottom: 1.2rem; }
/* Re-tuned for the light contact band. */
.contact-list svg { flex: 0 0 auto; width: 22px; height: 22px; margin-top: .35rem; fill: none; stroke: var(--brand); stroke-width: 1.8; }
.contact-list b { display: block; font-size: .85rem; color: var(--ink-3); font-weight: 700; }
.contact-list a { color: var(--brand); font-weight: 700; font-size: 1.05rem; }
.contact-list a:hover { color: var(--brand-dark); }

.form-field { margin-bottom: 1.15rem; }
.form-field label { display: block; font-weight: 700; margin-bottom: .35rem; }
.form-field .hint { display: block; font-size: .87rem; color: var(--ink-3); font-weight: 500; margin-bottom: .35rem; }
.form-field input, .form-field textarea, .form-field select {
  width: 100%;
  min-height: 48px;
  padding: .7rem .9rem;
  font: inherit;
  color: var(--ink);
  background: #fff;
  border: 2px solid var(--line-strong);
  border-radius: var(--r-s);
}
.form-field textarea { min-height: 8rem; resize: vertical; }
.form-field input:hover, .form-field textarea:hover { border-color: var(--ink-3); }
.req { color: #a8210b; font-weight: 800; }
.field-error { display: block; margin-top: .35rem; font-size: .9rem; font-weight: 700; color: #a8210b; }
[aria-invalid="true"] { border-color: #a8210b !important; background: #fff5f3; }
.form-status { margin-top: 1rem; padding: .9rem 1.1rem; border-radius: var(--r-s); font-weight: 700; }
.form-status:empty { display: none; }
.form-status[data-tone="ok"] { background: #e7f5ec; color: #14512f; border: 1px solid #9fcfb3; }
.form-status[data-tone="err"] { background: #fdecea; color: #8c1c07; border: 1px solid #e3a99f; }

/* --------------------------------------------------------------- footer */
/* Light footer. The dark navy slab was the last large blue area on the page;
   a grey footer keeps the whole document neutral. Note the markup still
   points at logo-white.webp, which would vanish here — swapped to the dark
   lockup in the HTML. */
.site-footer { background: var(--surface-3); color: var(--ink-2); padding-block: clamp(3rem, 6vw, 4.5rem) 0; }
.site-footer h2, .site-footer h3 { color: var(--ink); font-size: 1.02rem; letter-spacing: .05em; text-transform: uppercase; margin-bottom: 1rem; }
.footer-grid { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: .55rem; }
.site-footer a { color: var(--ink-2); text-decoration: none; }
.site-footer a:hover { color: var(--brand-dark); text-decoration: underline; }
.site-footer img { width: 150px; margin-bottom: 1rem; background: none; }
.footer-bottom {
  margin-top: 3rem;
  padding-block: 1.5rem;
  border-top: 1px solid var(--line-strong);
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  align-items: center; justify-content: space-between;
  font-size: .9rem;
}

/* Social profiles. 44px circles: comfortably past the 24px floor of WCAG
   2.5.8, and big enough to hit with a thumb in the footer on a phone. The
   name of each network lives in visually-hidden text, since an icon-only
   link otherwise announces as nothing at all. */
.site-footer .social {
  display: flex;
  gap: .6rem;
}
.site-footer .social li { margin: 0; }
.site-footer .social a {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.site-footer .social a:hover {
  color: #fff;
  background: var(--brand);
  border-color: var(--brand);
  text-decoration: none;
}
.site-footer .social svg { width: 20px; height: 20px; fill: currentColor; }
@media (prefers-reduced-motion: reduce) {
  .site-footer .social a { transition: none; }
}

/* =========================================================================
   Accessibility toolbar  —  סרגל נגישות
   ========================================================================= */
.a11y-launch {
  position: fixed;
  inset-block-start: auto;
  inset-block-end: 1.25rem;
  inset-inline-start: 1.25rem;
  z-index: 1000;
  width: 56px; height: 56px;
  display: grid; place-items: center;
  background: var(--brand);
  color: #fff;
  border: 3px solid #fff;
  border-radius: 50%;
  box-shadow: 0 4px 18px rgba(4,32,63,.35);
  cursor: pointer;
}
.a11y-launch:hover { background: var(--brand-dark); }
.a11y-launch svg { width: 30px; height: 30px; fill: currentColor; }

/* On narrow screens the launcher sits over the contact form — it covered the
   message field and clipped 36px off the submit button. When the focused
   control would be underneath it, step aside. Keeps the launcher reachable
   (it is never hidden, only moved) and keeps the focused control fully
   visible, per 2.4.11 Focus Not Obscured. */
.a11y-launch--dodge { transform: translateY(-5.75rem); }

/* Nothing should end up permanently trapped beneath the launcher. The room is
   added inside the footer rather than on <body>, which would show a strip of
   page background below the dark footer. */
@media (max-width: 47.99em) {
  .site-footer .footer-bottom { padding-block-end: 5.5rem; }
}

.a11y-panel {
  position: fixed;
  inset-block-end: 6.25rem;
  inset-inline-start: 1.25rem;
  z-index: 1001;
  width: min(21rem, calc(100vw - 2.5rem));
  max-height: min(32rem, calc(100dvh - 9rem));
  overflow-y: auto;
  background: #fff;
  color: var(--ink);
  border: 2px solid var(--brand);
  border-radius: var(--r-m);
  box-shadow: var(--shadow-m);
  padding: 1.25rem;
}
.a11y-panel[hidden] { display: none; }
.a11y-panel h2 { font-size: 1.15rem; margin: 0 0 .9rem; display: flex; align-items: center; gap: .5rem; }
.a11y-panel__close {
  margin-inline-start: auto;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  background: transparent; border: 2px solid var(--line-strong); border-radius: var(--r-s);
  color: var(--ink); font-size: 1.25rem; line-height: 1; cursor: pointer;
}
.a11y-panel__close:hover { background: var(--surface-2); border-color: var(--brand); }

.a11y-group { margin-bottom: 1.1rem; }
.a11y-group > h3 { font-size: .82rem; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-3); margin-bottom: .5rem; }
.a11y-steps { display: flex; align-items: center; gap: .5rem; }
.a11y-steps output { flex: 1; text-align: center; font-weight: 800; font-variant-numeric: tabular-nums; }
.a11y-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 44px; min-width: 44px;
  padding: .5rem .8rem;
  background: var(--surface-2);
  border: 2px solid var(--line-strong);
  border-radius: var(--r-s);
  font: inherit; font-weight: 700; color: var(--ink);
  cursor: pointer; text-align: start;
}
.a11y-btn:hover { background: var(--brand-tint); border-color: var(--brand); }
.a11y-btn[aria-pressed="true"] { background: var(--brand); border-color: var(--brand); color: #fff; }
.a11y-btn[aria-pressed="true"]::after { content: " ✓"; font-weight: 800; }
.a11y-toggles { display: grid; gap: .45rem; }
.a11y-toggles .a11y-btn { width: 100%; justify-content: flex-start; }
.a11y-panel .btn { width: 100%; }
.a11y-panel__note { font-size: .84rem; color: var(--ink-3); margin: 1rem 0 0; }

/* ---- toolbar effects (applied to <html>) ---- */
html[data-a11y-contrast="high"] {
  --ink: #000; --ink-2: #000; --ink-3: #1a1a1a;
  --surface: #fff; --surface-2: #fff; --surface-3: #fff;
  --brand: #00307a; --brand-dark: #001d4d; --brand-deep: #000; --brand-tint: #fff;
  --core-ink: #00307a; --line: #000; --line-strong: #000;
}
html[data-a11y-contrast="high"] body { background: #fff; }
html[data-a11y-contrast="high"] .hero__media::after { background: rgba(0,0,0,.86); }
html[data-a11y-contrast="high"] .hero .lede,
html[data-a11y-contrast="high"] .badges span,
html[data-a11y-contrast="high"] .hero-stats dt,
html[data-a11y-contrast="high"] .site-footer,
html[data-a11y-contrast="high"] .contact-list b { color: #fff; }
html[data-a11y-contrast="high"] .card,
html[data-a11y-contrast="high"] .table-wrap,
html[data-a11y-contrast="high"] .acc { border-width: 2px; }
html[data-a11y-contrast="high"] .badges,
html[data-a11y-contrast="high"] .band--brand,
html[data-a11y-contrast="high"] thead th { background: #00307a; }
html[data-a11y-contrast="high"] .site-footer { background: #000; }

html[data-a11y-contrast="dark"] {
  --ink: #f2f6fb; --ink-2: #d3dded; --ink-3: #adbcd1;
  --surface: #0d1826; --surface-2: #142234; --surface-3: #1b2c42;
  --brand: #8cc2f5; --brand-dark: #b6d9fa; --brand-deep: #060e18;
  --brand-tint: #182b42; --brand-tint-2: #1e3b5a;
  --core-ink: #7ec9ec; --line: #2c4157; --line-strong: #44607d;
  --focus: #ffb24d;
}
html[data-a11y-contrast="dark"] body { background: #0d1826; color: #f2f6fb; }
html[data-a11y-contrast="dark"] .site-header { background: #0d1826; }   /* opaque, as above */
html[data-a11y-contrast="dark"] .card,
html[data-a11y-contrast="dark"] .acc,
html[data-a11y-contrast="dark"] .table-wrap,
html[data-a11y-contrast="dark"] .a11y-panel,
html[data-a11y-contrast="dark"] .certs li { background: var(--surface-2); }
html[data-a11y-contrast="dark"] .badges,
html[data-a11y-contrast="dark"] .band--brand,
html[data-a11y-contrast="dark"] .badges li { background: #10243c; }
html[data-a11y-contrast="dark"] .badges li { color: #f2f6fb; }
html[data-a11y-contrast="dark"] thead th { background: #1b3a5e; color: #fff; }
html[data-a11y-contrast="dark"] .btn--primary { background: #8cc2f5; color: #06182c; border-color: #8cc2f5; }
html[data-a11y-contrast="dark"] .btn--primary:hover { background: #b6d9fa; color: #06182c; }
html[data-a11y-contrast="dark"] .a11y-btn[aria-pressed="true"] { background: #8cc2f5; color: #06182c; }
html[data-a11y-contrast="dark"] a:focus-visible, html[data-a11y-contrast="dark"] button:focus-visible {
  box-shadow: 0 0 0 6px #0d1826, 0 0 0 9px var(--focus);
}
html[data-a11y-contrast="dark"] img:not([src*="logo"]) { filter: brightness(.92); }

/* Greyscale is applied to the three content regions, NOT to <body>.

   A non-`none` filter makes an element the containing block for its
   position:fixed descendants. Filtering <body> therefore re-anchored the
   toolbar launcher, its panel and the reading guide to the body box instead
   of the viewport — on this page that threw the launcher ~19,000px down, to
   the bottom of the document. It read as "the icon disappeared", and it
   stranded the user: the control needed to switch greyscale back off had
   scrolled out of reach. `filter: none` on a descendant cannot undo an
   ancestor's containing block, so the old override was inert.

   Filtering the regions instead keeps the filter off the fixed UI's ancestor
   chain. The toolbar stays in colour, which also keeps the control that
   reverses the setting visually identifiable. */
html[data-a11y-saturation="grayscale"] .site-header,
html[data-a11y-saturation="grayscale"] main,
html[data-a11y-saturation="grayscale"] .site-footer { filter: grayscale(1); }

html[data-a11y-links="on"] :is(main, footer, header) a:not(.btn):not(.brand-link) {
  text-decoration: underline !important;
  text-decoration-thickness: .12em !important;
  background: #fff3c4;
  color: #1c2b1e !important;
  box-shadow: 0 0 0 2px #fff3c4;
  border-radius: 2px;
}
html[data-a11y-links="on"] .btn { outline: 3px dashed currentColor; outline-offset: 3px; }

html[data-a11y-font="readable"] {
  --ff: "Arial", "Helvetica Neue", "Arial Hebrew", sans-serif;
}
html[data-a11y-font="readable"] body { letter-spacing: .015em; word-spacing: .1em; }

/* The wordmark's "BOARD" half is near-black and vanishes on the dark header,
   so swap in the all-white lockup that the footer already uses. */
html[data-a11y-contrast="dark"] .brand-link img {
  content: url("../img/logo-white.webp");
}
/* Pass/fail markers keep their meaning but need a light-on-dark value. */
html[data-a11y-contrast="dark"] td .ok { color: #6ee7a8; }   /* 10.4:1 on --surface-2 */

html[data-a11y-spacing="on"] body { line-height: 2 !important; letter-spacing: .12em; word-spacing: .16em; }
html[data-a11y-spacing="on"] p { margin-bottom: 2em; }

html[data-a11y-motion="off"] *,
html[data-a11y-motion="off"] *::before,
html[data-a11y-motion="off"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
  scroll-behavior: auto !important;
}

html[data-a11y-cursor="big"], html[data-a11y-cursor="big"] * {
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 48 48'><path d='M6 2 L6 38 L15 30 L21 44 L28 41 L22 27 L34 27 Z' fill='%23000' stroke='%23fff' stroke-width='2.5'/></svg>") 4 2, auto !important;
}

/* reading guide bar */
.a11y-guide {
  position: fixed;
  inset-inline: 0;
  height: 2.6rem;
  z-index: 1002;
  pointer-events: none;
  border-block: 3px solid #b8340a;
  background: rgba(184, 52, 10, .14);
}
.a11y-guide[hidden] { display: none; }

/* =========================================================== rich content */
.prose { max-width: 74ch; }
.prose h2 { margin-top: 2.5em; }
.prose h2:first-of-type { margin-top: 0; }
.prose h3 { margin-top: 1.8em; font-size: var(--step-1); }
.prose ul { padding-inline-start: 1.3em; }
.prose li { margin-bottom: .55em; }
.prose dl { margin: 0 0 1.2em; }
.prose dt { font-weight: 800; margin-top: .9em; }
.prose dd { margin: 0 0 .3em; padding-inline-start: 1.1em; color: var(--ink-2); }

.callout {
  border: 1px solid var(--line);
  border-inline-start: 5px solid var(--brand);
  background: var(--surface-2);
  border-radius: var(--r-s);
  padding: 1.15rem 1.35rem;
  margin: 1.6rem 0;
}
.callout > :last-child { margin-bottom: 0; }
.callout h2, .callout h3 { margin-top: 0; font-size: var(--step-1); }
.callout h3 { font-size: 1.08rem; }

/* ------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* --------------------------------------------------------------- print */
@media print {
  .site-header, .a11y-launch, .a11y-panel, .a11y-guide, .skip-links, .btn-row, form { display: none !important; }
  body { color: #000; background: #fff; font-size: 11pt; }
  .hero__media { position: static; }
  .hero__media::after { display: none; }
  .hero, .band--brand, .badges, .site-footer { background: #fff !important; color: #000 !important; }
  .hero h1, .band--brand h2, .site-footer h3 { color: #000 !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  .band { padding-block: 1.2rem; }
}

/* ----------------------------------------------------- forced colors mode */
@media (forced-colors: active) {
  .btn, .a11y-btn, .card, .table-wrap, .acc { border: 1px solid ButtonBorder; }
  .badges svg, .feature-list .ico svg, .contact-list svg { stroke: CanvasText; }
  .hero__media::after { background: Canvas; opacity: .85; }
  :focus-visible { outline: 3px solid Highlight; }
}
