/* ==================================================================
   C-Hive v2

   Palette lock:  white + one blue. No second accent anywhere.
   Theme lock:    LIGHT. White is the brand, so the page does not
                  follow prefers-color-scheme. A dark palette exists
                  under [data-theme="dark"] but nothing turns it on
                  automatically.
   Shape lock:    cards 18px, buttons pill, inputs 12px.
   ================================================================== */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* ---- colour -------------------------------------------------
     The ground is a cool off-white, not #fff. Pure white across a
     whole viewport glares and flattens; cards sit at true white on
     top of it, which is what gives the page depth instead of a
     lightbox. Still reads white and blue.
     -------------------------------------------------------------- */
  --paper:      #edf2f9;   /* the ground */
  --card:       #ffffff;   /* things that sit on top of it */
  --surface:    #e5edf7;   /* strip, footer, tinted bands */
  --surface-2:  #dde8f5;
  --ink:        #0d1b2a;
  --ink-soft:   #4a5c71;
  --ink-faint:  #78899e;
  --line:       #d7e3f2;

  --blue:       #1462d8;
  --blue-hover: #0f52ba;
  --blue-tint:  #eaf2ff;

  /* ---- type --------------------------------------------------- */
  --font: 'IBM Plex Sans Arabic', 'IBM Plex Sans', system-ui, sans-serif;
  /* Latin glyphs take the mono, Arabic falls through per-glyph to the
     sans. That is how the specs read technical without breaking Arabic. */
  --font-mono: 'IBM Plex Mono', 'IBM Plex Sans Arabic', ui-monospace, monospace;

  /* ---- shape -------------------------------------------------- */
  --r-card:  18px;
  --r-input: 12px;
  --r-pill:  999px;

  /* ---- motion ------------------------------------------------- */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  /* small overshoot, so the bee lands like something with mass
     instead of sliding to a stop. Used on the bee only. */
  --ease-settle: cubic-bezier(0.34, 1.4, 0.64, 1);

  --t-ui:   180ms;
  --t-fly:  920ms;
  --t-exit: 780ms;
  --t-hold: 240ms;


  /* The five baked graphics. A data URI cannot read a CSS variable, so
     each theme supplies its own copy here and the usage sites just point
     at var(--g-*). Redefining these is the whole of theming them. */
  --g-comb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='45.03' height='78' viewBox='0 0 45.03 78'%3E%3Cpath fill='none' stroke='%231462d8' stroke-opacity='0.085' stroke-width='1' d='M22.52 -26L45.04 -13L45.04 13L22.52 26L0 13L0 -13ZM0 13L22.52 26L22.52 52L0 65L-22.52 52L-22.52 26ZM45.03 13L67.55 26L67.55 52L45.03 65L22.51 52L22.51 26ZM22.52 52L45.04 65L45.04 91L22.52 104L0 91L0 65Z'/%3E%3C/svg%3E");
  --g-blob: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='620' height='300' viewBox='0 0 620 300' preserveAspectRatio='none'%3E%3Cpath d='M34 150 C 34 100, 66 64, 118 56 C 170 48, 202 72, 252 64 C 306 55, 332 28, 392 32 C 452 36, 472 68, 522 76 C 574 84, 604 108, 600 152 C 596 198, 562 218, 514 228 C 464 238, 432 264, 374 268 C 314 272, 288 248, 234 252 C 178 256, 142 276, 96 256 C 52 236, 34 200, 34 150 Z' fill='%23a8c8f5'/%3E%3Cpath d='M108 86 C 152 64, 208 82, 256 74' fill='none' stroke='%23ffffff' stroke-width='12' stroke-linecap='round' opacity='.5'/%3E%3Cpath d='M424 54 C 464 57, 490 75, 518 88' fill='none' stroke='%23ffffff' stroke-width='8' stroke-linecap='round' opacity='.34'/%3E%3C/svg%3E");
  --g-blob-m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='620' height='300' viewBox='0 0 620 300' preserveAspectRatio='none'%3E%3Cpath d='M18 150 C 18 92, 46 26, 104 14 C 158 4, 206 8, 262 10 C 320 12, 350 30, 404 40 C 460 50, 486 74, 530 84 C 580 94, 606 114, 602 156 C 598 202, 562 222, 514 232 C 464 242, 432 268, 374 272 C 314 276, 288 252, 234 256 C 178 260, 142 280, 96 260 C 52 240, 18 204, 18 150 Z' fill='%23a8c8f5'/%3E%3Cpath d='M112 42 C 156 22, 212 36, 258 30' fill='none' stroke='%23ffffff' stroke-width='11' stroke-linecap='round' opacity='.5'/%3E%3Cpath d='M438 64 C 478 68, 502 84, 530 96' fill='none' stroke='%23ffffff' stroke-width='8' stroke-linecap='round' opacity='.34'/%3E%3C/svg%3E");
  --g-pot: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='330' viewBox='0 0 280 330'%3E%3Cpath d='M197 140 C 210 158, 232 176, 258 182 L 280 187 L 280 143 C 254 136, 226 132, 203 122 Z' fill='%23a8c8f5'/%3E%3Cpath d='M212 148 C 230 162, 250 172, 268 177' fill='none' stroke='%23ffffff' stroke-width='7' stroke-linecap='round' opacity='.5'/%3E%3Cg transform='rotate(18 130 210)'%3E%3Cpath d='M94 122 C 62 144, 54 198, 72 240 C 92 284, 168 284, 188 240 C 206 198, 198 144, 166 122 Z' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6.5' stroke-linejoin='round'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182 L 197 216 C 160 228, 100 228, 63 216 Z' fill='%231462d8' opacity='.15'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182' fill='none' stroke='%231462d8' stroke-width='4'/%3E%3Cpath d='M63 216 C 100 228, 160 228, 197 216' fill='none' stroke='%231462d8' stroke-width='4'/%3E%3Cpath d='M130 189 L141 195.5 L141 208.5 L130 215 L119 208.5 L119 195.5 Z' fill='none' stroke='%231462d8' stroke-width='3.6'/%3E%3Crect x='88' y='104' width='84' height='18' rx='9' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6.5'/%3E%3Cg transform='rotate(-11 80 96) translate(0,-3)'%3E%3Cellipse cx='130' cy='96' rx='50' ry='14' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6'/%3E%3Cpath d='M84 94 C 94 72, 166 72, 176 94' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6' stroke-linejoin='round'/%3E%3Ccircle cx='130' cy='66' r='10' fill='%23a8c8f5' stroke='%231462d8' stroke-width='5.5'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  --g-drops: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='120' viewBox='0 0 300 120'%3E%3Cpath d='M28 40 C 44 34, 62 40, 66 52 C 70 66, 54 76, 38 72 C 22 68, 14 48, 28 40 Z' fill='%23a8c8f5'/%3E%3Cellipse cx='128' cy='86' rx='19' ry='13' fill='%23a8c8f5'/%3E%3Cellipse cx='226' cy='38' rx='13' ry='9' fill='%23a8c8f5'/%3E%3Cellipse cx='272' cy='92' rx='8.5' ry='6' fill='%23a8c8f5'/%3E%3C/svg%3E");
  --g-hex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 115'%3E%3Cpath d='M50 2 L96 30 L96 85 L50 113 L4 85 L4 30 Z' fill='%23ffffff' fill-opacity='.5' stroke='%231462d8' stroke-opacity='.55' stroke-width='2.6' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* The stage colour ramp for the bee scenes. These MUST be variables:
     site.js used to hold the five hexes directly, so the scenes stayed pale
     in dark mode while everything around them went dark. */
  --ramp-0: #eff4fb;
  --ramp-1: #e4edf8;
  --ramp-2: #d8e6f6;
  --ramp-3: #e6eef9;
  --ramp-4: #eff4fb;

  --g-pot-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='430' viewBox='0 0 280 430'%3E%3Cpath d='M197 140 C 202 184, 190 226, 176 268 C 162 312, 142 372, 122 430 L 180 430 C 196 372, 212 312, 222 268 C 232 224, 224 172, 203 122 Z' fill='%23a8c8f5'/%3E%3Cpath d='M205 162 C 208 200, 197 240, 184 282 C 172 322, 156 372, 142 424' fill='none' stroke='%23ffffff' stroke-width='7' stroke-linecap='round' opacity='.5'/%3E%3Cg transform='rotate(18 130 210)'%3E%3Cpath d='M94 122 C 62 144, 54 198, 72 240 C 92 284, 168 284, 188 240 C 206 198, 198 144, 166 122 Z' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6.5' stroke-linejoin='round'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182 L 197 216 C 160 228, 100 228, 63 216 Z' fill='%231462d8' opacity='.15'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182' fill='none' stroke='%231462d8' stroke-width='4'/%3E%3Cpath d='M63 216 C 100 228, 160 228, 197 216' fill='none' stroke='%231462d8' stroke-width='4'/%3E%3Cpath d='M130 189 L141 195.5 L141 208.5 L130 215 L119 208.5 L119 195.5 Z' fill='none' stroke='%231462d8' stroke-width='3.6'/%3E%3Crect x='88' y='104' width='84' height='18' rx='9' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6.5'/%3E%3Cg transform='rotate(-11 80 96) translate(0,-3)'%3E%3Cellipse cx='130' cy='96' rx='50' ry='14' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6'/%3E%3Cpath d='M84 94 C 94 72, 166 72, 176 94' fill='%23a8c8f5' stroke='%231462d8' stroke-width='6' stroke-linejoin='round'/%3E%3Ccircle cx='130' cy='66' r='10' fill='%23a8c8f5' stroke='%231462d8' stroke-width='5.5'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");

  --nav-h: 66px;
  --z-nav: 40;
  --z-skip: 60;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Proximity, not mandatory. Snapping is no longer what carries the
     feeling here (the pinned stage below does that), so this only needs
     to be strong enough to land one step per gesture without hijacking
     the ordinary sections. */
  scroll-snap-type: y proximity;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }

:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; border-radius: 4px; }

.skip {
  position: absolute; inset-inline-start: 1rem; top: -100px; z-index: var(--z-skip);
  background: var(--blue); color: #fff; padding: .7rem 1.2rem; border-radius: var(--r-pill);
  transition: top var(--t-ui) var(--ease-out);
}
.skip:focus { top: 1rem; }

/* ---- layout ---------------------------------------------------- */

.wrap { width: 100%; max-width: 1240px; margin-inline: auto; padding-inline: clamp(1.25rem, 4vw, 2.5rem); }

/* The section label. It used to be .76rem mono with heavy tracking, which was
   effectively invisible above a 4rem headline, and in Arabic it was worse than
   invisible: letter-spacing pulls cursive letters apart, so the word came out
   disjointed. It is now a comb-cell badge, which reads at a glance and does not
   depend on uppercase (Arabic has no case). */
.eyebrow {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--font-mono);
  font-size: .84rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--blue);
  background: var(--blue-tint);
  border: 1px solid color-mix(in srgb, var(--blue) 26%, transparent);
  padding: .36rem .85rem .36rem .65rem;
  border-radius: var(--r-pill);
  margin-bottom: 1.1rem;
}
.eyebrow::before {
  content: ''; flex: none; width: 9px; height: 10px;
  background: var(--blue);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* Arabic is cursive, so tracking added for the Latin case breaks the joins.
   Zero it wherever a label carries letter-spacing. */
html[dir="rtl"] .eyebrow,
html[dir="rtl"] .foot h4,
html[dir="rtl"] .plan__tag,
html[dir="rtl"] .foot__base { letter-spacing: 0; }
html[dir="rtl"] .eyebrow { font-family: var(--font); padding-inline: .65rem .85rem; }

h1, h2, h3 { line-height: 1.15; font-weight: 700; letter-spacing: -.02em; }
h1 { font-size: clamp(2.3rem, 5.4vw, 3.9rem); }
h2 { font-size: clamp(1.85rem, 3.9vw, 2.9rem); }
h3 { font-size: clamp(1.1rem, 1.8vw, 1.35rem); font-weight: 600; }

.lede { font-size: clamp(1.02rem, 1.5vw, 1.18rem); color: var(--ink-soft); max-width: 60ch; }
.muted { color: var(--ink-soft); }
.small { font-size: .92rem; }

/* ---- buttons --------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5rem; white-space: nowrap;
  padding: .8rem 1.6rem;
  border: 2px solid transparent; border-radius: var(--r-pill);
  font-weight: 600; cursor: pointer;
  transition: background-color var(--t-ui) var(--ease-out),
              border-color var(--t-ui) var(--ease-out),
              color var(--t-ui) var(--ease-out),
              transform 120ms var(--ease-out);
}
.btn--primary { background: var(--blue); color: #fff; }
.btn--ghost   { background: transparent; color: var(--blue); border-color: var(--line); }
:root[data-theme="dark"] .btn--primary { color: #06101f; }
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover { background: var(--blue-hover); }
  .btn--ghost:hover   { border-color: var(--blue); background: var(--blue-tint); }
}
.btn:active { transform: scale(.975); }
.btn-row { display: flex; flex-wrap: wrap; gap: .8rem; }

/* invisible ruler the nav watches so it can contract without a
   scroll listener */
.nav-sentinel { position: absolute; top: 0; left: 0; width: 1px; height: 52px; pointer-events: none; }

/* ---- nav ---------------------------------------------------------
   Not a full-width bar. A detached pill that floats over the page, so
   the header reads as an object rather than as the top edge of a
   template. It contracts once you leave the hero (sentinel + observer,
   no scroll listener).
   ------------------------------------------------------------------ */

.nav {
  position: sticky; top: 0; z-index: var(--z-nav);
  padding-top: .85rem; padding-bottom: .3rem;
  background: none; border: 0;
}
.nav__in {
  height: var(--nav-h);
  /* hug the content: a stretched pill leaves dead air between the brand
     and the first page title, which is what `margin-inline-start:auto`
     on .nav__links was creating */
  width: max-content;
  max-width: calc(100% - 1.5rem);
  margin-inline: auto;
  padding-inline: 1.15rem .5rem;
  display: flex; align-items: center; gap: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--card) 80%, transparent);
  backdrop-filter: blur(18px) saturate(1.35);
  box-shadow: 0 16px 36px -24px rgba(13, 27, 42, .38),
              inset 0 1px 0 rgba(255, 255, 255, .75);
  transition: height var(--t-ui) var(--ease-out),
              box-shadow var(--t-ui) var(--ease-out),
              background-color var(--t-ui) var(--ease-out);
}
.nav[data-stuck="1"] .nav__in {
  height: 56px;
  background: color-mix(in srgb, var(--card) 92%, transparent);
  box-shadow: 0 18px 40px -26px rgba(13, 27, 42, .5),
              inset 0 1px 0 rgba(255, 255, 255, .8);
}

.nav__brand { display: flex; align-items: center; gap: .6rem; font-weight: 700; font-size: 1.1rem; }
.nav__brand svg { width: 28px; height: 28px; color: var(--blue); }
.nav__links { display: flex; align-items: center; gap: 1.15rem; }
/* :not(.btn) matters. Without it this rule outranks .btn--primary and the
   nav CTA renders grey on blue, which fails contrast badly. */
.nav__links a:not(.btn) {
  position: relative; isolation: isolate;
  font-size: .93rem; font-weight: 600; color: var(--ink-soft);
  transition: color var(--t-ui) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .nav__links a:not(.btn):hover { color: var(--blue); } }
/* the current page sits in its own comb cell */
.nav__links a:not(.btn)[aria-current="page"] { color: var(--blue); }
/* Vertical inset is deliberately small. This cell draws above the board
   (the link is its own stacking context), so any extra height here paints
   over the riser and node and the trace reads as cut off. site.js measures
   the label bottom and stops the riser below this cell. */
.nav__links a:not(.btn)[aria-current="page"]::before {
  content: ''; position: absolute; inset: -.28rem -.72rem; z-index: -1;
  background: var(--blue-tint);
  clip-path: polygon(15% 0, 85% 0, 100% 50%, 85% 100%, 15% 100%, 0 50%);
}
.nav__hex { display: none; }
.nav__end { display: flex; align-items: center; gap: .5rem; margin-inline-start: .4rem; }

/* A saturated pill inside a pale glass pill was the loudest thing on the page
   and fought the header. Tinted fill, blue label, blue-tinted edge: still the
   primary action, 5.3:1 on contrast, and it fills solid on hover so the
   affordance survives. */
.nav__end .btn--primary {
  background: var(--blue-tint);
  color: var(--blue);
  border-color: color-mix(in srgb, var(--blue) 32%, transparent);
  padding: .58rem 1.15rem;
  font-size: .9rem;
}
@media (hover: hover) and (pointer: fine) {
  .nav__end .btn--primary:hover {
    background: var(--blue);
    color: #fff;
    border-color: var(--blue);
  }
}
:root[data-theme="dark"] .nav__end .btn--primary { color: var(--blue); }
:root[data-theme="dark"] .nav__end .btn--primary:hover { color: #06101f; }

.lang {
  border: 1px solid var(--line); background: transparent; border-radius: var(--r-pill);
  padding: .3rem .75rem; font-family: var(--font-mono); font-size: .78rem; font-weight: 600; cursor: pointer;
  transition: border-color var(--t-ui) var(--ease-out), color var(--t-ui) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .lang:hover { border-color: var(--blue); color: var(--blue); } }

.nav__burger { display: none; background: none; border: 0; cursor: pointer; font-size: 1.55rem; line-height: 1; color: var(--ink); }

@media (max-width: 1080px) {
  /* No position:relative here on purpose. The sheet anchors to .nav, which is
     sticky and full width, so it lines up with the header instead of with the
     pill's narrower padding box. */
  .nav__in { width: auto; max-width: none; }
  .nav__burger {
    display: grid; place-items: center;
    width: 38px; height: 38px;
    margin-inline-start: auto;
    border-radius: var(--r-pill);
    color: var(--ink);
  }

  .nav__links {
    position: absolute;
    left: clamp(.75rem, 3vw, 1.5rem);
    right: clamp(.75rem, 3vw, 1.5rem);
    top: calc(var(--nav-h) + 1.15rem);
    flex-direction: column; align-items: stretch; gap: .15rem;
    margin: 0; padding: .6rem;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 20px;
    box-shadow: 0 26px 60px -28px rgba(13, 27, 42, .5);

    /* eased open rather than a hard display swap */
    opacity: 0; visibility: hidden;
    transform: translateY(-8px) scale(.985);
    transform-origin: top center;
    transition: opacity 190ms var(--ease-out),
                transform 190ms var(--ease-out),
                visibility 190ms;
  }
  .nav[data-open="1"] .nav__links {
    opacity: 1; visibility: visible; transform: none;
  }

  /* The desktop board, turned vertical: a trace running down through comb
     cells, one per page, with the current page's cell filled. */
  .nav__links { gap: 0; }

  .nav__links a:not(.btn) {
    position: relative; isolation: isolate;
    display: flex; align-items: center; gap: .75rem;
    padding: .62rem .7rem;
    border-bottom: 0;
    border-radius: 12px;
    font-size: 1rem;
  }

  /* the bus. One segment per row, and rows are contiguous, so the segments
     join into a single line with the cells sitting on it as nodes. */
  .nav__links a:not(.btn)::after {
    content: ''; position: absolute; z-index: -1;
    inset-inline-start: calc(.7rem + 15px);
    top: 0; bottom: 0; width: 1.6px;
    background: color-mix(in srgb, var(--blue) 26%, transparent);
  }
  .nav__links a:not(.btn):first-child::after { top: 50%; }
  .nav__links a:not(.btn):nth-last-child(2)::after { bottom: 50%; }

  .nav__hex {
    display: grid; place-items: center;
    flex: none; width: 30px; height: 34px;
    /* longhands, not the shorthand: var() inside `background` becomes a
       pending-substitution value and silently fails to resolve. Same trap that
       stopped the honey blob from theming. */
    background-image: var(--g-hex);
    background-position: center;
    background-size: contain;
    background-repeat: no-repeat;
    color: var(--blue);
  }
  .nav__hex i { font-size: .95rem; line-height: 1; }

  .nav__links a:not(.btn)[aria-current="page"] {
    background: var(--blue-tint);
    color: var(--blue);
    font-weight: 700;
  }
  /* the current page reads as a seated component, not an outline */
  .nav__links a:not(.btn)[aria-current="page"] .nav__hex {
    background-image: none;
    background-color: var(--blue);
    clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
    color: #fff;
  }
  :root[data-theme="dark"] .nav__links a[aria-current="page"] .nav__hex { color: #06101f; }
  .nav__links a:not(.btn)[aria-current="page"]::before { display: none; }
  @media (hover: hover) and (pointer: fine) {
    .nav__links a:not(.btn):hover { background: var(--surface); }
  }

  /* controls on a grid so the CTA takes whatever width is left */
  .nav__end {
    margin-inline-start: 0;
    margin-top: .45rem;
    padding-top: .6rem;
    border-top: 1px solid var(--line);
    display: grid;
    grid-template-columns: auto auto 1fr;
    gap: .5rem;
    align-items: center;
  }
  .nav__end .btn { width: 100%; }
  .lang { height: 32px; }
}

@media (prefers-reduced-motion: reduce) {
  .nav__links { transition: opacity 120ms linear, visibility 120ms; transform: none; }
  .nav[data-open="1"] .nav__links { transform: none; }
}



/* ---- the nav board ----------------------------------------------
   The header is the one hard break in an otherwise calm page, so it
   carries the tech register for the whole site: a trace bus with solder
   nodes under the page titles, and current running along it.

   This is not a new motif. The C-Hive logomark is already a honeycomb
   cell with circuit traces and round nodes coming off it. This is that
   mark's language applied to the header.

   Geometry is measured from the real link positions in site.js, because
   label widths change with the language toggle and with the viewport.
   Everything lives in the bottom band of the pill, under the text
   baseline, so no trace ever sits behind a glyph.
   ---------------------------------------------------------------- */

.nav__in { position: relative; isolation: isolate; }
.nav__board {
  position: absolute; inset: 0; z-index: -1;
  width: 100%; height: 100%;
  pointer-events: none; overflow: visible;
}

/* the bus and its risers draw themselves once, left to right */
.nav__board .trace {
  fill: none; stroke: var(--blue); stroke-width: 1.4;
  stroke-linecap: round; opacity: .32;
  stroke-dasharray: var(--len, 600); stroke-dashoffset: var(--len, 600);
  animation: trace-draw 1.1s var(--ease-out) forwards;
  animation-delay: .35s;
}
.nav__board .trace--riser { stroke-width: 1.3; opacity: .26; animation-delay: calc(.75s + var(--n) * .06s); }
@keyframes trace-draw { to { stroke-dashoffset: 0; } }

/* solder nodes, drawn like the ones on the logomark: filled dot, light ring */
.nav__board .node {
  fill: var(--card); stroke: var(--blue); stroke-width: 1.6;
  opacity: 0; animation: node-in 320ms var(--ease-out) forwards;
  animation-delay: calc(1.05s + var(--n) * .06s);
}
.nav__board .node--core { fill: var(--blue); stroke: var(--card); stroke-width: .8; opacity: 0; animation: node-in 320ms var(--ease-out) forwards; animation-delay: calc(1.15s + var(--n) * .06s); }
@keyframes node-in { to { opacity: .7; } }

/* the current: a short bright dash travelling the length of the bus.
   stroke-dashoffset rather than a moving element, so there is nothing
   to keep in sync and no SMIL. */
.nav__board .pulse {
  fill: none; stroke: var(--blue); stroke-width: 2.2; stroke-linecap: round;
  stroke-dasharray: 16 2000; stroke-dashoffset: 2016;
  opacity: .85; filter: drop-shadow(0 0 3px color-mix(in srgb, var(--blue) 55%, transparent));
  animation: pulse-flow var(--dur, 3.4s) linear infinite;
  animation-delay: var(--delay, 0s);
}
@keyframes pulse-flow { to { stroke-dashoffset: 0; } }

/* the page you are on is a component seated on the board */
.nav__board .node[data-live="1"] { animation-name: node-in-live; }
@keyframes node-in-live { to { opacity: 1; } }

/* hovering a page title energises its own node and riser */
.nav__board [data-n].is-hot { opacity: 1; transition: opacity 140ms var(--ease-out); }

/* the phone gets its own simpler board, built in site.js */

@media (prefers-reduced-motion: reduce) {
  .nav__board .trace, .nav__board .trace--riser { animation: none; stroke-dashoffset: 0; opacity: .3; }
  .nav__board .node, .nav__board .node--core { animation: none; opacity: .7; }
  .nav__board .pulse { display: none; }
}

/* ---- the honeycomb field --------------------------------------
   Ties the page back to the logomark and gives the white space
   something structural underneath. Kept very faint on purpose: it
   should read as engineering paper, not as wallpaper.
   ---------------------------------------------------------------- */

.beat {
  background-color: var(--paper);
  background-image: var(--g-comb);
  background-position: center top;
}

/* ---- hero --------------------------------------------------------
   The signature moment, not another section. Three layers of depth:
   a honeycomb that draws itself on load, a swarm of nine small bees
   drifting on their own periods, and one full-detail bee up front.
   Everything decorative is pointer-events:none and aria-hidden.
   ------------------------------------------------------------------ */

.hero {
  position: relative; overflow: clip;
  min-height: min(94dvh, 860px);
  display: grid; align-items: center;
  padding-top: clamp(2rem, 5vw, 3.5rem);
  padding-bottom: clamp(3rem, 8vw, 6rem);
}
.hero__grid {
  position: relative; z-index: 2;
  display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .hero__grid { grid-template-columns: 1.1fr .9fr; } }

.hero h1 {
  font-size: clamp(2.5rem, 6.2vw, 4.4rem);
  letter-spacing: -.035em; line-height: 1.05;
  margin-bottom: 1.15rem;
}
.hero .lede { margin-bottom: 2rem; }
.hero__art { position: relative; display: grid; place-items: center; min-height: 300px; }
.hero__art .bee-float { width: clamp(210px, 30vw, 330px); color: var(--blue); }

/* the comb sits behind the mascot, bleeding off the outer edge */
.hero__comb {
  position: absolute; z-index: 1;
  inset-inline-end: -7%; top: 48%;
  width: min(48vw, 540px);
  transform: translateY(-50%);
  color: var(--blue); opacity: .42;
  pointer-events: none;
}
.comb { width: 100%; height: auto; }
.comb__cell {
  stroke-dasharray: 340; stroke-dashoffset: 340;
  animation: comb-draw 1s var(--ease-out) forwards;
  animation-delay: calc(.3s + var(--n) * .12s);
}
@keyframes comb-draw { to { stroke-dashoffset: 0; } }

/* the swarm spans the whole hero, part of it behind the copy */
.hero__swarm { position: absolute; inset: 0; overflow: clip; pointer-events: none; }
.swarm__bee {
  position: absolute; display: block; color: var(--blue);
  animation-name: swarm-dart;
  animation-timing-function: var(--ease-in-out);
  animation-iteration-count: infinite;
}
.swarm__bee[data-tier="back"]  { opacity: .3;  z-index: 0; }
.swarm__bee[data-tier="front"] { opacity: .5;  z-index: 3; }
.bee--mini { width: 100%; height: auto; overflow: visible; }
.bee--mini .bee-wing--l { transform-origin: 92% 88%; }
.bee--mini .bee-wing--r { transform-origin: 8% 88%; }

/* The flight keyframes are generated per bee in bees.js, one @keyframes each,
   because a single shared block cannot give nine bees different loops, rhythms
   and headings. animation-name is set inline on each bee. */

/* a holding bee still corrects itself constantly */
/* Hovering is not a sine wave. Uneven stops and an off-centre return read as
   a bee holding station against the air rather than bobbing on a spring. */
@keyframes bee-micro {
  0%   { transform: translate(0, -2.5px) rotate(-2.4deg); }
  28%  { transform: translate(1.5px, 1.8px) rotate(1.6deg); }
  54%  { transform: translate(-1px, -1.2px) rotate(-1deg); }
  76%  { transform: translate(0.8px, 2.4px) rotate(2.2deg); }
  100% { transform: translate(0, -2.5px) rotate(-2.4deg); }
}
.swarm__bee .bee--mini {
  animation: bee-micro var(--micro, 0.7s) ease-in-out infinite;
}

@media (max-width: 860px) {
  .hero { min-height: auto; }
  .hero__comb { inset-inline-end: -26%; width: 78vw; opacity: .3; }
  /* thin the swarm: nine drifting bees on a phone is noise */
  .swarm__bee:nth-child(even) { display: none; }
}

/* ---- the stack --------------------------------------------------
   This replaced a row of grey monochrome logos. Six unlabelled marks
   with no heading read as a "trusted by" wall, which was doubly wrong:
   they are technologies, not customers, and nobody could tell what any
   of them was doing there. Now each one is named, tinted to the single
   brand blue, seated in a comb cell, and says what it does in a line.
   ------------------------------------------------------------------ */

.stack__grid { list-style: none; display: grid; gap: 1rem 2rem; grid-template-columns: 1fr; }
@media (min-width: 620px)  { .stack__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .stack__grid { grid-template-columns: repeat(3, 1fr); } }

.stack__item {
  display: flex; align-items: center; gap: .95rem;
  padding: 1rem 1.15rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
.stack__cell {
  flex: none; width: 54px; height: 60px;
  display: grid; place-items: center;
  background: var(--blue-tint);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
/* One icon family at one weight, and a glyph centres reliably inside the
   cell. Six third-party brand marks did not: different visual weights,
   different optical centres, and a CDN that could leave holes. The
   vendor is named in the text instead. */
.stack__cell i { font-size: 1.5rem; color: var(--blue); line-height: 1; }
/* Scoped to the text column on purpose. `.stack__item span` would also
   match .stack__cell (it is a span too) and, at one class plus one element,
   it outranks .stack__cell and forces display:block, which silently kills
   the grid centering and drops the icon into the RTL start corner. Second
   time this exact trap has bitten in this file: see the nav CTA. */
.stack__item div b { display: block; font-size: .98rem; font-weight: 600; letter-spacing: -.01em; }
.stack__item div span { display: block; color: var(--ink-soft); font-size: .89rem; line-height: 1.5; }

/* ==================================================================
   THE BEAT - the bee choreography
   ------------------------------------------------------------------
   Layers, one transform each, never combined:
     .beat__bee   flight        (transition, JS toggles the class)
     .bee-float   idle life     (keyframe, always running)
     svg.bee      facing        (static scaleX)
     g.bee-wing   flap          (keyframe)

   The flight is an ARC, not a slide: the bee enters from below its
   resting line and leaves rising. Sides are physical (viewport left
   and right), so it behaves the same in Arabic and English.

   scroll-snap-stop: always is what makes this stop feeling like
   scrolling. One gesture moves you exactly one beat, so the page
   reads as the bee swapping the content out rather than as a long
   document going past.
   ================================================================== */

/* ---- the reel ---------------------------------------------------
   This is what stops it feeling like scrolling.

   The beats are lifted out of the document flow into one sticky,
   viewport-height stage, and all of them are stacked on top of each
   other inside it. The scroll length comes from invisible step markers
   behind the stage, one per beat.

   So while you are in the reel the page does not visually move at all.
   Scrolling advances a step index, and the only thing that changes is
   which bee is holding the content: the current one leaves through the
   far edge, and the next arrives a beat later carrying the new copy.
   Nothing slides past, so there is nothing that reads as a document
   going by.

   Built by site.js from plain <section class="beat"> siblings, so the
   markup stays flat and readable and works with JS off.
   ---------------------------------------------------------------- */

.reel { position: relative; }

.reel__stage {
  position: sticky; top: 0;
  height: 100dvh;
  overflow: clip;
  background-image: var(--g-comb);
}

/* every beat occupies the whole stage, stacked, so the outgoing and the
   incoming bee share the same space and the handover is visible */
.reel__stage .beat {
  position: absolute; inset: 0;
  min-height: 0; height: 100%;
  padding-block: 0;
  background: none;
}
/* only the beat currently on stage can be clicked or tabbed into */
.reel__stage .beat:not(.is-in) { pointer-events: none; }

/* the scroll length. pulled up under the stage so the reel is exactly
   one viewport per beat. */
.reel__steps { margin-top: -100dvh; }
.reel__step {
  height: 100dvh;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}

.beat {
  --enter:       58vw;
  --exit:      -120vw;
  --rise:        13vh;   /* how far below the resting line it enters */
  --climb:      -11vh;   /* how far it climbs on the way out */
  --tilt-in:     -6deg;
  --tilt-out:    18deg;
  --body-enter:  7vw;
  --body-exit: -17vw;
  --body-tilt-in:   2.5deg;
  --body-tilt-out: -4deg;
  --body-origin: right center;

  position: relative;
  min-height: 100dvh;
  display: grid;
  align-items: center;
  padding-block: clamp(4rem, 10vh, 7rem);
  overflow: clip;
}
.beat[data-side="left"] {
  --enter:     -58vw;
  --exit:      120vw;
  --tilt-in:    6deg;
  --tilt-out: -18deg;
  --body-enter: -7vw;
  --body-exit:  17vw;
  --body-tilt-in:  -2.5deg;
  --body-tilt-out:  4deg;
  --body-origin: left center;
}
/* kept so existing markup stays valid, but white is the stage now */
.beat--tinted { background-color: var(--surface); }

.beat__in { position: relative; z-index: 2; width: 100%; }

.beat__body { max-width: 30rem; }
/* physical, not logical: bee right means body left in Arabic AND English */
.beat[data-side="right"] .beat__body { margin-right: auto; margin-left: 0; }
.beat[data-side="left"]  .beat__body { margin-left: auto; margin-right: 0; }
.beat__body h2 { margin-bottom: 1rem; }
/* Copy on the honey is full ink, not --ink-soft: at 10.1:1 it is comfortable,
   where --ink-soft only manages 4.0:1 on this tint. */
.beat__body,
.beat__body h2,
.beat__body h3,
.beat__body .lede,
.beat__body p { color: var(--ink); }
.beat__body .eyebrow { color: var(--blue); }

/* A ghost button is blue on transparent, only 3.25:1 against the honey. The
   card as a ground puts it back to 5.6:1 and makes it read as a control
   sitting on the pour rather than dissolved into it. */
.beat__body .btn--ghost {
  background: var(--card);
  color: var(--blue);
  border-color: color-mix(in srgb, var(--blue) 26%, var(--line));
}
.beat__body .btn--primary {
  background: var(--blue);
  color: #fff;
  border-color: var(--blue);
}
@media (hover: hover) and (pointer: fine) {
  .beat__body .btn--primary:hover { background: var(--blue-hover); }
  .beat__body .btn--ghost:hover { background: var(--card); border-color: var(--blue); }
}

/* the work rows sit on the honey, so they keep their own light card */
.beat__body .work__meta b { color: var(--ink); }
.beat__body .work__meta span { color: var(--ink-soft); }
.beat__body .work__link { color: var(--blue); border-color: var(--line); background: var(--card); }
/* the pour rises 224px above the panel, so the scene needs the room */
.beat { padding-block: clamp(4rem, 12vh, 8.5rem); }
.beat__body .lede { margin-bottom: 1.5rem; }

.beat__bee {
  position: absolute; top: 50%;
  width: clamp(200px, 26vw, 340px);
  color: var(--blue);
  pointer-events: none;
}
/* The bee lives inside .wrap, so a positive offset also inherits the
   container's padding and it ends up much closer to the copy than the number
   suggests. Pulling it slightly negative pushes it out toward the stage edge
   and opens the gap the panel needs. */
.beat[data-side="right"] .beat__bee { right: clamp(-2.5rem, -1vw, 0rem); }
.beat[data-side="left"]  .beat__bee { left:  clamp(-2.5rem, -1vw, 0rem); }

/* The parked-and-invisible start state is gated behind .chive-js, set by an
   inline script in <head>. Without JS the page is a plain readable document
   instead of a stack of empty sections, and crawlers see the copy. */
.chive-js .beat__bee {
  transform: translate(var(--enter), calc(-50% + var(--rise))) rotate(var(--tilt-in));
  opacity: 0;
  transition: transform var(--t-fly) var(--ease-out),
              opacity 420ms var(--ease-out);
}

/* arrived, with a touch of overshoot as it settles */
.beat.is-in .beat__bee {
  transform: translate(0, -50%) rotate(var(--tilt-in));
  opacity: 1;
  transition: transform var(--t-fly) var(--ease-settle),
              opacity 420ms var(--ease-out);
  transition-delay: var(--t-hold), var(--t-hold);
}

/* away through the opposite edge, climbing and banking */
.beat.is-out .beat__bee {
  transform: translate(var(--exit), calc(-50% + var(--climb))) rotate(var(--tilt-out));
  opacity: 0;
  transition: transform var(--t-exit) var(--ease-in-out),
              opacity 520ms linear 240ms;
}

/* The content is carried by the bee, so it does not simply slide: it
   arrives tilted and slightly small, straightens as it is set down, and
   on the way out it tips the other way, shrinks and goes. That is what
   makes it read as being taken away rather than scrolled past. */
.chive-js .beat__body > * {
  opacity: 0;
  /* small: the panel above carries the journey, these only need to arrive
     in sequence so the line the bee sets down first is read first */
  transform: translateY(10px);
  transition: transform var(--t-fly) var(--ease-out),
              opacity 460ms var(--ease-out);
}
.beat.is-in .beat__body > * {
  opacity: 1;
  transform: translateY(0);
  /* 60ms stagger so the line the bee sets down first is read first */
  transition-delay: calc(var(--t-hold) + var(--i, 0) * 60ms);
}
.beat.is-out .beat__body > * {
  opacity: 0;
  transform: translateY(-8px);
  transition: transform var(--t-exit) var(--ease-in-out),
              opacity 320ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 40ms);
}

/* ---- the background ramp ---------------------------------------
   The ground does not cut from one section colour to the next. Each
   beat owns a target colour, and the stage eases between them, so while
   you scroll the reel the background shifts continuously underneath the
   content.

   Driven by the step observer in site.js rather than a scroll-driven
   animation: `animation-timeline` is still uneven across browsers, and a
   transition here behaves identically everywhere. If you want it locked
   to the scrollbar frame by frame instead of eased between stops, that is
   the one thing to swap.
   ---------------------------------------------------------------- */

.reel__stage {
  background-color: var(--stage-bg, var(--paper));
  transition: background-color 900ms var(--ease-in-out);
}

@media (prefers-reduced-motion: reduce) {
  .reel__stage { transition: background-color 200ms linear; }
}

/* If the observers never report (see the bailout in site.js), the reel
   must not stay pinned with every beat stacked on top of the next. This
   unwinds it to a plain readable stack. */
.reel[data-off="1"] .reel__stage { position: static; height: auto; overflow: visible; }
.reel[data-off="1"] .beat { position: static; height: auto; min-height: 60vh; padding-block: 3rem; }
.reel[data-off="1"] .reel__steps { display: none; }



/* ---- the bee gets annoyed ---------------------------------------
   Press a bee and it pulls a face. Three of them, cycled, so a second
   press is not the same joke.

   Every transform layer is already in use (flight on .beat__bee, hover
   on .bee-float, facing on svg.bee, flap on g.bee-wing), so the shake
   goes on the face group, which has no transform of its own, and the
   wings just beat harder. Nothing fights the choreography.
   ---------------------------------------------------------------- */

.beat.is-in .beat__bee,
.hero__art [data-bee] { pointer-events: auto; cursor: pointer; }

.bee-facepart { transform-box: fill-box; transform-origin: center; }

.is-annoyed .bee-facepart { animation: face-shake 320ms ease-in-out 3; }
.is-annoyed .bee-wing--l,
.is-annoyed .bee-wing--r { animation-duration: 68ms; }

@keyframes face-shake {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  22%      { transform: translateX(-3.5px) rotate(-3deg); }
  58%      { transform: translateX(3.5px)  rotate(3deg); }
  80%      { transform: translateX(-1.5px) rotate(-1.5deg); }
}

@media (prefers-reduced-motion: reduce) {
  .is-annoyed .bee-facepart { animation: none; }
  .is-annoyed .bee-wing--l, .is-annoyed .bee-wing--r { animation: none; }
}

/* ---- the shards -------------------------------------------------
   Two or three hexagon images per bee scene. Positions are authored
   per scene in the markup, not randomised, so the scatter is stable
   across loads and never collides with the copy. They ride the same
   choreography as the text: carried in by the bee, carried back out.

   The slots are empty until real pictures exist. An <img> with no src
   is hidden and the figure shows a labelled placeholder instead, so
   adding src is the only change needed. Every intended subject and
   size is in an HTML comment beside its slot.
   ---------------------------------------------------------------- */

/* Behind everything. .beat__in is position:relative with z-index auto, so a
   positive z-index here lifted the shards above both the bee and the copy.
   Pinning the content layer explicitly keeps that from coming back. */
.shards { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
/* the cells themselves are draggable, so they opt back into pointer events
   while their container stays transparent to clicks */
.shard { pointer-events: auto; cursor: grab; touch-action: none; }
.shard.is-dragging {
  cursor: grabbing;
  z-index: 5;
  transition: none !important;   /* follow the pointer exactly */
}

.shard {
  /* left, top and width are set by placeShards() in site.js from the
     measured free bands, so a cell can never land on the bee or the copy. */
  position: absolute;
  aspect-ratio: .866;                       /* true hexagon proportion */
  margin: 0;
  display: none;                            /* until placed */
  place-items: center;
  background-image: var(--g-hex);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
.shard i {
  font-size: var(--isz, 44px);
  line-height: 1;
  color: var(--blue);
  opacity: .62;
}
.shard__tag {
  font-family: var(--font-mono);
  font-size: calc(var(--isz, 44px) * .36);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--blue);
  opacity: .68;
  white-space: nowrap;
}
/* the hero cell of each scene carries a touch more presence */
.shard--hero { opacity: 1; }
.shard--hero i, .shard--hero .shard__tag { opacity: .8; }

/* carried with the bee, same as the copy, on their own short stagger */
.chive-js .shard {
  opacity: 0;
  transform: translateX(var(--body-enter)) rotate(var(--r)) scale(.9);
  transition: transform var(--t-fly) var(--ease-out),
              opacity 460ms var(--ease-out);
}
.beat.is-in .shard {
  opacity: .78;
  transform: translateX(0) rotate(var(--r)) scale(1);
  transition-delay: calc(var(--t-hold) + var(--d, 0ms));
}
.beat.is-out .shard {
  opacity: 0;
  transform: translateX(var(--body-exit)) rotate(var(--r)) scale(.86);
  transition: transform var(--t-exit) var(--ease-in-out),
              opacity 400ms var(--ease-out);
  transition-delay: var(--d, 0ms);
}

/* no room for them once the scene stacks vertically */
/* the cells stay on mobile; placeShards() thins and shrinks them there */

@media (prefers-reduced-motion: reduce) {
  .chive-js .shard, .beat.is-in .shard, .beat.is-out .shard {
    transform: rotate(var(--r));
    transition: opacity 240ms var(--ease-out);
    transition-delay: 0ms;
  }
}



/* ---- the honeypot pour ------------------------------------------
   Built from the reference: the pot stands BESIDE the copy, tipped, with
   a lid and a dipper; the honey leaves its lip and sweeps sideways in an
   S into an organic lobed blob, and that blob is the copy container.
   Loose droplets sit off its far edge.

   The blob is one SVG at 620x300, close to the panel's real proportions,
   so stretching it to the actual box barely moves the lobes. Text keeps
   generous padding because the lobes eat into the corners.

   COLOUR: honey is amber in the reference and blue here, because the
   palette is locked to white plus one blue. To take the reference's amber
   instead, change --honey and --honey-deep below; nothing else refers to
   those two values.
   ---------------------------------------------------------------- */

:root {
  --honey: #a8c8f5;
  --honey-deep: #8db4ee;
}

.beat__body {
  position: relative;
  background-image: var(--g-blob);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
  border-radius: 0;
  box-shadow: none;
  /* the lobes cut into the corners, so the copy is inset well clear of them */
  padding: clamp(2.2rem, 3.6vw, 3.2rem) clamp(2.6rem, 4vw, 3.6rem);
}

/* the pot, beside the blob rather than above it */
.beat__body::before {
  content: '';
  position: absolute; top: 50%;
  width: 280px; height: 330px;
  /* exactly half the graphic: the ribbon exits at its vertical centre,
     so it meets the blob's centre line at any panel height */
  margin-top: -165px;
  background-image: var(--g-pot);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 280px 330px;
  pointer-events: none;
}
/* the stream must run INTO the blob, so the pot sits on the outer side and
   the whole graphic mirrors when the scene flips */
.beat[data-side="right"] .beat__body::before { left: -246px; }
.beat[data-side="left"]  .beat__body::before { right: -246px; transform: scaleX(-1); }

/* loose droplets off the far edge */
.beat__body::after {
  content: '';
  position: absolute; bottom: -46px;
  width: 300px; height: 120px;
  background-image: var(--g-drops);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  pointer-events: none;
}
.beat[data-side="right"] .beat__body::after { right: -78px; }
.beat[data-side="left"]  .beat__body::after { left: -78px; transform: scaleX(-1); }

/* the pot needs room beside the copy, so pull the panel off the outer edge */
/* Narrower panel and a smaller outer margin both pull the panel's inner edge
   away from the bee. At 1400px the gap goes from about 26px to about 156px. */
.beat[data-side="right"] .beat__body { margin-left: clamp(0px, 15vw, 224px); }
.beat[data-side="left"]  .beat__body { margin-right: clamp(0px, 15vw, 224px); }

@media (max-width: 1180px) {
  .beat__body::before { width: 210px; height: 248px; background-size: 210px 248px; margin-top: -124px; }
  .beat[data-side="right"] .beat__body::before { left: -184px; }
  .beat[data-side="left"]  .beat__body::before { right: -184px; }
  .beat[data-side="right"] .beat__body { margin-left: 190px; }
  .beat[data-side="left"]  .beat__body { margin-right: 190px; }
}

@media (max-width: 860px) {
  /* the scene stacks, so the pot goes above the blob and pours down */
  .beat__body {
    padding: clamp(1.8rem, 6vw, 2.4rem) clamp(1.6rem, 5vw, 2.2rem);
    /* A pool whose surface rises to meet a stream arriving from above.
       The desktop blob dips to y=59 of 300 at the pour's x, which on a
       520px panel is 102px down, leaving the ribbon ending in mid-air. */
    background-image: var(--g-blob-m);
  }
  .beat[data-side="right"] .beat__body,
  .beat[data-side="left"]  .beat__body { margin-left: auto !important; margin-right: auto !important; }
  /* The desktop graphic pours out of its RIGHT edge, which only works with
     the pot standing beside the copy. Stacked on mobile the pot sits above,
     so it needs the variant whose stream leaves the BOTTOM edge. */
  .beat__body::before {
    width: 168px; height: 258px;
    background-image: var(--g-pot-v);
    background-size: 168px 258px;
    /* the ribbon runs to the very bottom of the canvas, and this pulls it into
       the panel so the honey and the pool are one surface */
    top: auto; bottom: 100%; margin-top: 0; margin-bottom: -30px;
  }
  .beat[data-side="right"] .beat__body::before,
  .beat[data-side="left"]  .beat__body::before { left: 6%; right: auto; transform: none; }
  .beat__body::after { display: none; }
}

/* the panel is what the bee carries, so the travel moves to the panel and
   the children keep only their stagger. Without this the two would compound
   and the copy would slide twice as far as the bee. */
.chive-js .beat__body {
  opacity: 0;
  transform: translateX(var(--body-enter)) rotate(var(--body-tilt-in)) scale(.96);
  transform-origin: var(--body-origin);
  transition: transform var(--t-fly) var(--ease-out),
              opacity 460ms var(--ease-out);
}
.beat.is-in .beat__body {
  opacity: 1;
  transform: translateX(0) rotate(0deg) scale(1);
  transition-delay: var(--t-hold);
}
.beat.is-out .beat__body {
  opacity: 0;
  transform: translateX(var(--body-exit)) rotate(var(--body-tilt-out)) scale(.92);
  transition: transform var(--t-exit) var(--ease-in-out),
              opacity 420ms var(--ease-out);
}

/* A 186x155 landscape override used to live here from an earlier pot
   iteration. It came after the mobile pour block and so squashed the 200x250
   portrait graphic, and its inset-inline-start:50% fought the left:6% above.
   Removed rather than adjusted: the mobile block already sizes the pour. */

@media (prefers-reduced-motion: reduce) {
  .chive-js .beat__body,
  .beat.is-in .beat__body,
  .beat.is-out .beat__body {
    transform: none;
    transition: opacity 240ms var(--ease-out);
    transition-delay: 0ms;
  }
}

/* ---- the bee itself -------------------------------------------- */

.bee-float { width: 100%; animation: bee-hover 3.1s var(--ease-in-out) infinite; }
.bee { width: 100%; height: auto; overflow: visible; }
.beat[data-side="right"] .bee { transform: scaleX(-1); }  /* face into the page */

/* origin sits at the wing ROOT (where it meets the body), not the centre,
   so the flap pivots like a hinge instead of spinning about the middle */
.bee-wing { transform-box: fill-box; }
.bee-wing--l { transform-origin: 97% 53%; animation: bee-flap-l 118ms var(--ease-in-out) infinite alternate; }
.bee-wing--r { transform-origin: 3% 53%;  animation: bee-flap-r 118ms var(--ease-in-out) infinite alternate; }
.bee-blush { opacity: .45; }

/* a bee is never perfectly still: it drifts and it rolls a little */
@keyframes bee-hover {
  0%,100% { transform: translateY(-10px) rotate(-2deg); }
  50%     { transform: translateY(10px)  rotate(2deg); }
}
@keyframes bee-flap-l {
  from { transform: rotate(4deg)   scaleY(1);   }
  to   { transform: rotate(-26deg) scaleY(.74); }
}
@keyframes bee-flap-r {
  from { transform: rotate(-4deg) scaleY(1);   }
  to   { transform: rotate(26deg) scaleY(.74); }
}

/* mobile: the bee stops being a companion and becomes a header */
@media (max-width: 860px) {
  .beat { --enter: 44vw; --exit: -100vw; --rise: 9vh; --climb: -8vh; --body-enter: 5vw; --body-exit: -12vw; }
  .beat[data-side="left"] { --enter: -44vw; --exit: 100vw; --body-enter: -5vw; --body-exit: 12vw; }
  .beat__in { display: flex; flex-direction: column; align-items: center; gap: 1.5rem; text-align: center; }
  .beat__bee { position: static; top: auto; right: auto; left: auto; width: clamp(150px, 44vw, 220px); }
  .chive-js .beat__bee { transform: translate(var(--enter), var(--rise)) rotate(var(--tilt-in)); }
  .beat.is-in .beat__bee { transform: translate(0, 0) rotate(var(--tilt-in)); }
  .beat.is-out .beat__bee { transform: translate(var(--exit), var(--climb)) rotate(var(--tilt-out)); }
  .beat__body { max-width: 38rem; margin-left: auto !important; margin-right: auto !important; }
  .beat__body .btn-row { justify-content: center; }
}

/* ---- sections -------------------------------------------------- */

.section { padding-block: clamp(3.5rem, 9vw, 6.5rem); }
.section--tint { background: var(--surface); border-block: 1px solid var(--line); }
.section__head { max-width: 42rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.section__head h2 { margin-bottom: .8rem; }


/* ---- the work scene ---------------------------------------------
   The reel's last scene, so the sites we built are what you see right
   before the plans. Wider body than a normal beat: the bee shares the
   stage with three rows instead of one paragraph.

   No logo files exist for these clients yet (clients.json has empty
   logo fields), so each gets a comb-cell monogram. When real logos land
   in c-hive-site/uploads/clients/, swap the span for an <img>.
   ---------------------------------------------------------------- */

.beat--wide .beat__body { max-width: 42rem; }
.beat--wide .beat__bee { width: clamp(150px, 17vw, 215px); }

.work { list-style: none; display: grid; gap: .7rem; margin-top: .3rem; }
.work__item {
  display: flex; align-items: center; gap: 1rem;
  padding: .8rem 1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
.work__cell {
  flex: none; width: 46px; height: 52px;
  display: grid; place-items: center;
  background: var(--blue-tint); color: var(--blue);
  font-family: var(--font-mono); font-size: 1.15rem; font-weight: 600;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.work__meta { min-width: 0; }
.work__meta b { display: block; font-size: .98rem; font-weight: 600; }
.work__meta span { display: block; color: var(--ink-soft); font-size: .88rem; line-height: 1.5; }
.work__link {
  margin-inline-start: auto; flex: none;
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .85rem; font-weight: 600; color: var(--blue);
  padding: .35rem .7rem; border-radius: var(--r-pill);
  border: 1px solid var(--line);
  transition: border-color var(--t-ui) var(--ease-out), background-color var(--t-ui) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .work__link:hover { border-color: var(--blue); background: var(--blue-tint); }
}
.work__link i { font-size: 1rem; }
@media (max-width: 640px) {
  .work__item { flex-wrap: wrap; }
  .work__link { margin-inline-start: 0; }
}

/* service tiles are whole-tile links, so give them the press feedback */
.tile--link { text-decoration: none; transition: border-color var(--t-ui) var(--ease-out), transform 120ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .tile--link:hover { border-color: var(--blue); } }
.tile--link:active { transform: scale(.99); }

.plans { display: grid; gap: 1.25rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 780px)  { .plans { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .plans { grid-template-columns: repeat(3, 1fr); } }

.plan {
  position: relative; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 1.9rem 1.6rem; display: flex; flex-direction: column; gap: 1.1rem;
}
.plan--featured { border-color: var(--blue); box-shadow: 0 18px 50px -22px color-mix(in srgb, var(--blue) 34%, transparent); }
.plan__tag {
  position: absolute; top: -.8rem; inset-inline-start: 1.6rem;
  background: var(--blue); color: #fff;
  font-family: var(--font-mono); font-size: .72rem; font-weight: 600; letter-spacing: .04em;
  padding: .25rem .8rem; border-radius: var(--r-pill);
}
:root[data-theme="dark"] .plan__tag { color: #06101f; }
.plan__price { display: flex; align-items: baseline; gap: .3rem; }
.plan__price b { font-family: var(--font-mono); font-size: 2.8rem; font-weight: 600; letter-spacing: -.04em; line-height: 1; }
.plan__price span { color: var(--ink-faint); font-size: .95rem; }
.plan ul { list-style: none; display: grid; gap: .6rem; font-size: .96rem; }
.plan li { display: flex; gap: .55rem; align-items: flex-start; color: var(--ink-soft); }
.plan li i { color: var(--blue); font-size: 1.1rem; line-height: 1.5; flex: none; }
.plan .btn { margin-top: auto; }

.bento { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .bento { grid-template-columns: repeat(6, 1fr); } }
.tile {
  border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 1.5rem; background: var(--card);
  display: flex; flex-direction: column; gap: .6rem;
}
.tile i { font-size: 1.7rem; color: var(--blue); }
.tile p { color: var(--ink-soft); font-size: .96rem; }
.tile--wide  { grid-column: span 6; }
.tile--half  { grid-column: span 3; }
.tile--third { grid-column: span 2; }
@media (max-width: 759px) { .tile--wide, .tile--half, .tile--third { grid-column: auto; } }
.tile--accent {
  background: linear-gradient(150deg, var(--blue-tint), var(--card) 78%);
  border-color: color-mix(in srgb, var(--blue) 30%, var(--line));
}
/* An illustration slot. It holds inline SVG on currentColor rather than a
   photograph, so it themes with the page and there is no asset to source. */
.tile--art {
  padding: 1.25rem; overflow: hidden; min-height: 220px;
  display: grid; place-items: center;
  background: var(--blue-tint);
  border-color: color-mix(in srgb, var(--blue) 22%, var(--line));
}
.tile--art .art { width: 100%; height: auto; max-height: 260px; color: var(--blue); opacity: .85; }

/* the short list that lets a half-width tile carry its own weight */
.tile__list { list-style: none; display: grid; gap: .45rem; margin-top: .3rem; }
.tile__list li {
  position: relative; padding-inline-start: 1.1rem;
  font-size: .9rem; color: var(--ink-soft); line-height: 1.5;
}
.tile__list li::before {
  content: ''; position: absolute; inset-inline-start: 0; top: .55em;
  width: 7px; height: 8px;
  background: var(--blue);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.band { display: grid; gap: 2rem; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 820px) { .band { grid-template-columns: repeat(4, 1fr); } }
.band div b {
  display: block; font-family: var(--font-mono);
  font-size: clamp(1.9rem, 3.6vw, 2.6rem); font-weight: 600;
  letter-spacing: -.04em; color: var(--blue); line-height: 1.15;
}
.band div span { color: var(--ink-soft); font-size: .94rem; }

.prose { max-width: 62ch; }
.prose p { margin-bottom: 1.1rem; color: var(--ink-soft); }
.prose h2 { margin: 2.4rem 0 .9rem; }

/* ---- form ------------------------------------------------------ */

.form { display: grid; gap: 1.15rem; max-width: 34rem; }
.field { display: grid; gap: .4rem; }
.field label { font-weight: 600; font-size: .93rem; }
.field .hint { font-size: .84rem; color: var(--ink-soft); }
.field input, .field textarea {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-input);
  padding: .75rem .9rem;
  transition: border-color var(--t-ui) var(--ease-out), box-shadow var(--t-ui) var(--ease-out);
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-faint); }
.field input:focus, .field textarea:focus {
  outline: none; border-color: var(--blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 22%, transparent);
}
.field .error { font-size: .86rem; color: #b52d1c; min-height: 1.2em; }
:root[data-theme="dark"] .field .error { color: #ff8f80; }
.field[data-invalid="1"] input, .field[data-invalid="1"] textarea { border-color: #b52d1c; }

.form__note { font-size: .9rem; color: var(--ink-soft); }
.form__ok {
  display: none; gap: .6rem; align-items: center; margin-bottom: 1.5rem;
  background: var(--blue-tint); border: 1px solid color-mix(in srgb, var(--blue) 32%, var(--line));
  border-radius: var(--r-card); padding: 1rem 1.2rem;
}
.form__ok[data-show="1"] { display: flex; }
.form__ok i { color: var(--blue); font-size: 1.4rem; flex: none; }

.contact-list { list-style: none; display: grid; gap: 1.1rem; }
@media (min-width: 900px) { .contact-cols { grid-template-columns: 1.15fr .85fr !important; } }
.contact-list a, .contact-list span { display: flex; gap: .7rem; align-items: center; font-weight: 600; }
.contact-list i { color: var(--blue); font-size: 1.4rem; }

/* ---- footer ---------------------------------------------------- */

.foot { border-top: 1px solid var(--line); background: var(--surface); padding-block: clamp(2.5rem, 6vw, 4rem) 1.5rem; }
.foot__grid { display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .foot__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.foot h4 { font-family: var(--font-mono); font-size: .76rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: .9rem; }
.foot ul { list-style: none; display: grid; gap: .55rem; }
.foot a { color: var(--ink-soft); font-size: .95rem; transition: color var(--t-ui) var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .foot a:hover { color: var(--blue); } }
.foot__base { margin-top: 2.5rem; padding-top: 1.25rem; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: .75rem 1.5rem; justify-content: space-between; font-family: var(--font-mono); font-size: .82rem; color: var(--ink-faint); }

/* ---- reduced motion -------------------------------------------
   Fewer and gentler, not zero. The bee still arrives, it just does
   not fly, hover, or flap. Snapping is dropped too.
   ---------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }
  /* the swarm holds still and the comb is simply already drawn */
  .swarm__bee, .swarm__bee .bee--mini { animation: none; }
  .comb__cell { animation: none; stroke-dashoffset: 0; }
  /* unpin: back to a plain stack of readable sections */
  .reel__stage { position: static; height: auto; overflow: visible; }
  .reel__stage .beat { position: static; height: auto; min-height: 60vh; padding-block: 3rem; }
  .reel__steps { display: none; }
  .bee-float, .bee-wing { animation: none; }
  .chive-js .beat__bee,
  .beat.is-in .beat__bee,
  .beat.is-out .beat__bee {
    transform: translate(0, -50%) rotate(0deg);
    transition: opacity 260ms var(--ease-out);
  }
  @media (max-width: 860px) {
    .chive-js .beat__bee, .beat.is-in .beat__bee, .beat.is-out .beat__bee { transform: none; }
  }
  .chive-js .beat__body > *,
  .beat.is-in .beat__body > *,
  .beat.is-out .beat__body > * {
    transform: none; transition: opacity 240ms var(--ease-out); transition-delay: 0ms;
  }
  .beat { min-height: auto; }
  .btn:active { transform: none; }
}

/* ==================================================================
   DARK MODE
   ------------------------------------------------------------------
   Opt-in only. `data-theme="dark"` is set by the toggle in the nav and
   remembered; nothing reads prefers-color-scheme, because auto-dark is
   what made this site read dark against the brief in the first place.
   To follow the system instead, see the note in applyTheme().

   The five graphics below are background-image data URIs, and a data URI
   cannot read a CSS variable, so each one needs a dark twin here. The
   bees and the nav board traces are inline SVG on currentColor and adapt
   without any help.
   ================================================================== */

:root[data-theme="dark"] {
  color-scheme: dark;

  --paper:      #0b1220;
  --card:       #131f33;
  --surface:    #0f1a2c;
  --surface-2:  #16233a;
  --ink:        #e9f1fb;
  --ink-soft:   #a4b6cd;
  --ink-faint:  #7b8da6;
  --line:       #22334f;

  --blue:       #6ba5ff;
  --blue-hover: #8dbcff;
  --blue-tint:  #16273f;

  --g-comb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='45.03' height='78' viewBox='0 0 45.03 78'%3E%3Cpath fill='none' stroke='%236ba5ff' stroke-opacity='0.1' stroke-width='1' d='M22.52 -26L45.04 -13L45.04 13L22.52 26L0 13L0 -13ZM0 13L22.52 26L22.52 52L0 65L-22.52 52L-22.52 26ZM45.03 13L67.55 26L67.55 52L45.03 65L22.51 52L22.51 26ZM22.52 52L45.04 65L45.04 91L22.52 104L0 91L0 65Z'/%3E%3C/svg%3E");
  --g-blob: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='620' height='300' viewBox='0 0 620 300' preserveAspectRatio='none'%3E%3Cpath d='M34 150 C 34 100, 66 64, 118 56 C 170 48, 202 72, 252 64 C 306 55, 332 28, 392 32 C 452 36, 472 68, 522 76 C 574 84, 604 108, 600 152 C 596 198, 562 218, 514 228 C 464 238, 432 264, 374 268 C 314 272, 288 248, 234 252 C 178 256, 142 276, 96 256 C 52 236, 34 200, 34 150 Z' fill='%231d4f96'/%3E%3Cpath d='M108 86 C 152 64, 208 82, 256 74' fill='none' stroke='%23ffffff' stroke-width='12' stroke-linecap='round' opacity='.28'/%3E%3Cpath d='M424 54 C 464 57, 490 75, 518 88' fill='none' stroke='%23ffffff' stroke-width='8' stroke-linecap='round' opacity='.18'/%3E%3C/svg%3E");
  --g-blob-m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='620' height='300' viewBox='0 0 620 300' preserveAspectRatio='none'%3E%3Cpath d='M18 150 C 18 92, 46 26, 104 14 C 158 4, 206 8, 262 10 C 320 12, 350 30, 404 40 C 460 50, 486 74, 530 84 C 580 94, 606 114, 602 156 C 598 202, 562 222, 514 232 C 464 242, 432 268, 374 272 C 314 276, 288 252, 234 256 C 178 260, 142 280, 96 260 C 52 240, 18 204, 18 150 Z' fill='%231d4f96'/%3E%3Cpath d='M112 42 C 156 22, 212 36, 258 30' fill='none' stroke='%23ffffff' stroke-width='11' stroke-linecap='round' opacity='.28'/%3E%3Cpath d='M438 64 C 478 68, 502 84, 530 96' fill='none' stroke='%23ffffff' stroke-width='8' stroke-linecap='round' opacity='.18'/%3E%3C/svg%3E");
  --g-pot: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='330' viewBox='0 0 280 330'%3E%3Cpath d='M197 140 C 210 158, 232 176, 258 182 L 280 187 L 280 143 C 254 136, 226 132, 203 122 Z' fill='%231d4f96'/%3E%3Cpath d='M212 148 C 230 162, 250 172, 268 177' fill='none' stroke='%23ffffff' stroke-width='7' stroke-linecap='round' opacity='.34'/%3E%3Cg transform='rotate(18 130 210)'%3E%3Cpath d='M94 122 C 62 144, 54 198, 72 240 C 92 284, 168 284, 188 240 C 206 198, 198 144, 166 122 Z' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6.5' stroke-linejoin='round'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182 L 197 216 C 160 228, 100 228, 63 216 Z' fill='%23ffffff' opacity='.1'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182' fill='none' stroke='%237fb4ff' stroke-width='4'/%3E%3Cpath d='M63 216 C 100 228, 160 228, 197 216' fill='none' stroke='%237fb4ff' stroke-width='4'/%3E%3Cpath d='M130 189 L141 195.5 L141 208.5 L130 215 L119 208.5 L119 195.5 Z' fill='none' stroke='%237fb4ff' stroke-width='3.6'/%3E%3Crect x='88' y='104' width='84' height='18' rx='9' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6.5'/%3E%3Cg transform='rotate(-11 80 96) translate(0,-3)'%3E%3Cellipse cx='130' cy='96' rx='50' ry='14' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6'/%3E%3Cpath d='M84 94 C 94 72, 166 72, 176 94' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6' stroke-linejoin='round'/%3E%3Ccircle cx='130' cy='66' r='10' fill='%231d4f96' stroke='%237fb4ff' stroke-width='5.5'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  --g-drops: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='120' viewBox='0 0 300 120'%3E%3Cpath d='M28 40 C 44 34, 62 40, 66 52 C 70 66, 54 76, 38 72 C 22 68, 14 48, 28 40 Z' fill='%231d4f96'/%3E%3Cellipse cx='128' cy='86' rx='19' ry='13' fill='%231d4f96'/%3E%3Cellipse cx='226' cy='38' rx='13' ry='9' fill='%231d4f96'/%3E%3Cellipse cx='272' cy='92' rx='8.5' ry='6' fill='%231d4f96'/%3E%3C/svg%3E");
  --g-hex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 115'%3E%3Cpath d='M50 2 L96 30 L96 85 L50 113 L4 85 L4 30 Z' fill='%2316273f' fill-opacity='.65' stroke='%236ba5ff' stroke-opacity='.5' stroke-width='2.6' stroke-linejoin='round'/%3E%3C/svg%3E");

  --ramp-0: #0b1220;
  --ramp-1: #0e1728;
  --ramp-2: #131d33;
  --ramp-3: #0f1a2c;
  --ramp-4: #0b1220;

  --g-pot-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='430' viewBox='0 0 280 430'%3E%3Cpath d='M197 140 C 202 184, 190 226, 176 268 C 162 312, 142 372, 122 430 L 180 430 C 196 372, 212 312, 222 268 C 232 224, 224 172, 203 122 Z' fill='%231d4f96'/%3E%3Cpath d='M205 162 C 208 200, 197 240, 184 282 C 172 322, 156 372, 142 424' fill='none' stroke='%23ffffff' stroke-width='7' stroke-linecap='round' opacity='.34'/%3E%3Cg transform='rotate(18 130 210)'%3E%3Cpath d='M94 122 C 62 144, 54 198, 72 240 C 92 284, 168 284, 188 240 C 206 198, 198 144, 166 122 Z' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6.5' stroke-linejoin='round'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182 L 197 216 C 160 228, 100 228, 63 216 Z' fill='%23ffffff' opacity='.1'/%3E%3Cpath d='M63 182 C 100 194, 160 194, 197 182' fill='none' stroke='%237fb4ff' stroke-width='4'/%3E%3Cpath d='M63 216 C 100 228, 160 228, 197 216' fill='none' stroke='%237fb4ff' stroke-width='4'/%3E%3Cpath d='M130 189 L141 195.5 L141 208.5 L130 215 L119 208.5 L119 195.5 Z' fill='none' stroke='%237fb4ff' stroke-width='3.6'/%3E%3Crect x='88' y='104' width='84' height='18' rx='9' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6.5'/%3E%3Cg transform='rotate(-11 80 96) translate(0,-3)'%3E%3Cellipse cx='130' cy='96' rx='50' ry='14' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6'/%3E%3Cpath d='M84 94 C 94 72, 166 72, 176 94' fill='%231d4f96' stroke='%237fb4ff' stroke-width='6' stroke-linejoin='round'/%3E%3Ccircle cx='130' cy='66' r='10' fill='%231d4f96' stroke='%237fb4ff' stroke-width='5.5'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");

  --honey:      #1d4f96;
  --honey-deep: #143a70;
}

/* the honeycomb field, on both surfaces that carry it */

/* the pour */

/* the comb cells behind the scenes */

/* A white label on --blue is 2.5:1 once the blue lightens for dark, so the
   primary inside the pour takes a near-black label instead. */
:root[data-theme="dark"] .beat__body .btn--primary { color: #06101f; }
:root[data-theme="dark"] .btn--primary { color: #06101f; }
:root[data-theme="dark"] .plan__tag { color: #06101f; }

/* the pill's inset highlight is far too bright on a dark ground */
:root[data-theme="dark"] .nav__in {
  box-shadow: 0 16px 36px -20px rgba(0, 0, 0, .7),
              inset 0 1px 0 rgba(255, 255, 255, .08);
}
:root[data-theme="dark"] .nav[data-stuck="1"] .nav__in {
  box-shadow: 0 18px 44px -22px rgba(0, 0, 0, .85),
              inset 0 1px 0 rgba(255, 255, 255, .1);
}
:root[data-theme="dark"] .beat__body {
  box-shadow: none;
}
:root[data-theme="dark"] .work__item,
:root[data-theme="dark"] .stack__item,
:root[data-theme="dark"] .tile,
:root[data-theme="dark"] .plan { box-shadow: none; }

.theme {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 1px solid var(--line); background: transparent;
  border-radius: var(--r-pill); cursor: pointer; color: var(--ink-soft);
  transition: border-color var(--t-ui) var(--ease-out), color var(--t-ui) var(--ease-out);
}
.theme i { font-size: 1.05rem; line-height: 1; }
@media (hover: hover) and (pointer: fine) {
  .theme:hover { border-color: var(--blue); color: var(--blue); }
}
