/* BioCE shared shell (T-161). Loaded by every bioce.cloud public page.
   Rules of this file: every selector starts with .bx- so nothing here can
   restyle the host page; no element or global selectors, no resets. The
   fonts and the BioCE mark ship WITH the shell under /assets/bioce-shell/
   (no other origin is ever contacted, and a landing redesign that renames
   its own /assets/fonts/ or /assets/img/ cannot break every page's header).
   The header is in normal flow (not fixed or sticky), so a page's own sticky
   sub-navigation still sticks at the top once the shell scrolls away. */

@font-face {
  font-family: 'BioCE Shell';
  font-weight: 600;
  font-display: swap;
  src: url('/assets/bioce-shell/fonts/Inter-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'BioCE Shell';
  font-weight: 600;
  font-display: swap;
  src: url('/assets/bioce-shell/fonts/NotoSansThai-600-thai.woff2') format('woff2');
  unicode-range: U+0E01-0E5B, U+200C-200D, U+25CC;
}

/* ── Bar ─────────────────────────────────────────────────────────────────── */
/* Colour tokens (T-751). Dark is the default on every page. A mount that
   opts in with data-bx-schemes="light dark" turns light when EITHER the page
   carries html[data-scheme="light"] (set before first paint by the page's own
   pre-paint script, so a light page never shows a dark bar while the deferred
   shell.js loads, nor if it never runs) OR shell.js has mirrored the scheme
   onto the mount as data-bx-scheme="light". A mount without the opt-in stays
   dark whatever the page shows. A programme mount may carry
   data-bx-brand="pgcs": that bar is fully wine (wine ground, white ink, an
   inverted white account button) in BOTH schemes (T-759 = B, 2026-10-12).
   Every colour below derives from these tokens, so the hooks recolour the
   whole bar.
   --bx-accent-rgb is the accent as an "r, g, b" triple for rgba() tints,
   --bx-tint-rgb the hover/control wash, --bx-on-accent the account button
   text. Every text/background pair is at least 4.5:1 in all four variants
   (dark, light, PGCS dark, PGCS light), measured by ShellStyles in
   deploy/test_shell_adoption.py. */
.bx-shell {
  --bx-bg: #071426;
  --bx-ink: #eef4fb;
  --bx-body: #b9c6d9;
  --bx-accent: #35b8f0;
  --bx-accent-deep: #1f8fce;
  --bx-accent-rgb: 53, 184, 240;
  --bx-on-accent: #04121f;
  --bx-tint-rgb: 255, 255, 255;
  --bx-line: rgba(238, 244, 251, .12);
  --bx-line-strong: rgba(238, 244, 251, .24);
  --bx-font: 'BioCE Shell', system-ui, -apple-system, 'Segoe UI', Roboto, 'Noto Sans Thai', 'Leelawadee UI', Tahoma, sans-serif;

  position: relative;
  z-index: 1000;
  box-sizing: border-box;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  width: 100%;
  min-height: 60px;
  margin: 0;
  /* content aligns to a 1400px column on wide screens, 16px gutters on phones */
  padding: 10px max(16px, calc((100% - 1400px) / 2));
  border: 0;
  border-bottom: 1px solid var(--bx-line);
  background: var(--bx-bg);
  color: var(--bx-ink);
  font: 600 14px/1.3 var(--bx-font);
  font-synthesis: none;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  -webkit-font-smoothing: antialiased;
}
/* Light scheme (ratios against #ffffff: ink 16.7, body 9.1, white button
   text on the accent 5.1, on the deep stop 7.4). Two selectors, one palette
   (T-751): the first is set by shell.js, the second follows the page's
   html[data-scheme="light"] before shell.js runs; :is() keeps it starting
   with .bx- so it can never match the host page.
   Specificity (a rule applies with its most specific MATCHING selector):
     .bx-shell                                          0,1,0  base (dark)
     plain light, mount form  [data-bx-scheme]          0,2,0
     plain light, html form   [data-bx-schemes~]:is()   0,3,1
     PGCS wine, dark form     [data-bx-brand]           0,2,0
     PGCS wine, mount form    [brand][scheme]           0,3,0
     PGCS wine, html form     [brand][schemes~]:is()    0,4,1
   The three PGCS wine selectors share ONE rule and one palette (T-759 = B,
   2026-10-12: the PGCS bar is fully wine in both schemes). Its two light
   forms exist only to outrank plain light: on a light page (the html
   attribute is set before paint and kept in step by shell.js) the wine
   rule matches at 0,4,1 and beats plain light (0,3,1); with only the mount
   attribute it matches at 0,3,0 and beats plain light (0,2,0). The wine
   rule sets every token plain light sets, so no light value can reach a
   PGCS bar. */
.bx-shell[data-bx-scheme="light"],
.bx-shell[data-bx-schemes~="light"]:is(html[data-scheme="light"] *) {
  --bx-bg: #ffffff;
  --bx-ink: #0b1f33;
  --bx-body: #3a4a5e;
  --bx-accent: #1273b0;
  --bx-accent-deep: #0d5a8a;
  --bx-accent-rgb: 18, 115, 176;
  --bx-on-accent: #ffffff;
  --bx-tint-rgb: 7, 20, 38;
  --bx-line: rgba(7, 20, 38, .12);
  --bx-line-strong: rgba(7, 20, 38, .26);
}
/* PGCS brand hook (T-759 = B, 2026-10-12): the whole bar is wine in BOTH
   schemes, one rule, three selectors (dark form, light mount form, light
   html form; specificities listed above the light rule, where the light
   forms are shown to outrank plain light). It sets every token the plain
   light rule sets. Ground: the PGCS wine #760000. Text: white ink, pink
   body text #f9ccd2. The account button is inverted: wine text on a white
   to pink gradient. Washes, hover tints and lines are white, as on any dark
   ground. Ratios against #760000: ink 11.86, body 8.24, ink on the 14%
   current-page wash 8.97, ink on the 6% hover wash 10.67 and the 4% control
   wash 11.06; button text 11.86 on white and 8.24 on the pink stop; focus
   ring (white) 11.86. Comments stay above the rule, never inside its braces:
   a release invariant regex reads inside them. */
.bx-shell[data-bx-brand="pgcs"],
.bx-shell[data-bx-brand="pgcs"][data-bx-scheme="light"],
.bx-shell[data-bx-brand="pgcs"][data-bx-schemes~="light"]:is(html[data-scheme="light"] *) {
  --bx-bg: #760000;
  --bx-ink: #ffffff;
  --bx-body: #f9ccd2;
  --bx-accent: #ffffff;
  --bx-accent-deep: #f9ccd2;
  --bx-accent-rgb: 255, 255, 255;
  --bx-on-accent: #760000;
  --bx-tint-rgb: 255, 255, 255;
  --bx-line: rgba(255, 255, 255, .16);
  --bx-line-strong: rgba(255, 255, 255, .34);
}

/* ── Brand mark (also the no-JS fallback) ────────────────────────────────── */
.bx-brand {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  margin: 0 auto 0 0;
  padding: 0 4px 0 0;
  border-radius: 10px;
  color: var(--bx-ink);
  font: 600 19px/1 var(--bx-font);
  letter-spacing: -.01em;
  text-decoration: none;
}
/* The estate mark (the MedCMU cross), a 96 px copy of assets/img/bioce-mark.png
   so it stays sharp at 3x. Decorative: the link text "BioCE" names it. */
.bx-brand::before {
  content: '';
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: url('/assets/bioce-shell/bioce-mark.png') center / contain no-repeat;
}
.bx-brand:hover { color: var(--bx-ink); }

/* ── Navigation panel (built by shell.js) ────────────────────────────────── */
.bx-panel {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
}
.bx-nav { display: block; margin: 0; padding: 0; }
.bx-nav-list {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.bx-nav-item { display: block; margin: 0; padding: 0; }
.bx-nav-item::marker { content: none; }
.bx-nav-link {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 0 12px;
  border-radius: 999px;
  color: var(--bx-body);
  font: 600 14px/1.2 var(--bx-font);
  text-decoration: none;
  white-space: nowrap;
  transition: color .15s, background-color .15s;
}
.bx-nav-link:hover { color: var(--bx-ink); background: rgba(var(--bx-tint-rgb), .06); }
.bx-nav-link[aria-current="page"] {
  color: var(--bx-ink);
  background: rgba(var(--bx-accent-rgb), .14);
  box-shadow: inset 0 0 0 1px rgba(var(--bx-accent-rgb), .40);
}

/* ── Two-segment switches: language and colour scheme (T-780) ────────────── */
/* Each switch shows BOTH states and fills the one the page shows now
   (aria-checked="true": accent ground, on-accent text, a soft lift); the
   other segment is quiet body text on the bar. Ratios are measured in all
   four bar variants by ShellStyles in deploy/test_shell_adoption.py. */
.bx-switch {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 40px;
  margin: 0;
  padding: 3px;
  border: 1px solid var(--bx-line-strong);
  border-radius: 999px;
  background: rgba(var(--bx-tint-rgb), .04);
}
.bx-seg {
  -webkit-appearance: none;
  appearance: none;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  margin: 0;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--bx-body);
  font: 600 13px/1 var(--bx-font);
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
  transition: color .15s, background-color .15s;
}
.bx-seg:hover { color: var(--bx-ink); background: rgba(var(--bx-tint-rgb), .06); }
.bx-seg[aria-checked="true"],
.bx-seg[aria-checked="true"]:hover {
  background: var(--bx-accent);
  color: var(--bx-on-accent);
  box-shadow: 0 1px 6px rgba(var(--bx-accent-rgb), .35);
  cursor: default;
}
/* A segment the page cannot honour (a single-language page pins its
   language): it stays readable (same quiet colour, so contrast holds) but
   never reacts to hover and shows a not-allowed cursor; its title says why. */
.bx-seg[aria-disabled="true"],
.bx-seg[aria-disabled="true"]:hover {
  background: transparent;
  color: var(--bx-body);
  cursor: not-allowed;
}
.bx-seg-icon { font-size: 14px; line-height: 1; }

/* ── Menu button ─────────────────────────────────────────────────────────── */
.bx-menu {
  -webkit-appearance: none;
  appearance: none;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--bx-line-strong);
  border-radius: 999px;
  background: rgba(var(--bx-tint-rgb), .04);
  color: var(--bx-ink);
  font: 600 13px/1 var(--bx-font);
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
  transition: border-color .15s;
}
.bx-menu:hover { border-color: var(--bx-accent); }
.bx-menu { display: none; }
.bx-menu::after {
  content: '';
  width: 7px;
  height: 7px;
  margin-top: -4px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform .15s;
}
.bx-menu[aria-expanded="true"]::after { margin-top: 4px; transform: rotate(-135deg); }

/* ── The one account button (also the no-JS sign-in link) ────────────────── */
.bx-signin {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  margin: 0;
  padding: 0 18px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--bx-accent), var(--bx-accent-deep));
  color: var(--bx-on-accent);
  font: 600 14px/1.2 var(--bx-font);
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgba(var(--bx-accent-rgb), .22);
}
.bx-signin:hover { color: var(--bx-on-accent); filter: brightness(1.06); }

/* ── Visible keyboard focus on every control ─────────────────────────────── */
.bx-brand:focus-visible,
.bx-nav-link:focus-visible,
.bx-menu:focus-visible,
.bx-signin:focus-visible {
  outline: 3px solid var(--bx-ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px rgba(var(--bx-accent-rgb), .45);
}
/* A segment's ring sits in the 4 px gap and 3 px padding of its own switch
   (ink on the switch wash, measured >= 3:1), so it never paints over the
   neighbouring segment. */
.bx-seg:focus-visible {
  outline: 3px solid var(--bx-ink);
  outline-offset: 1px;
}

/* ── Narrow screens: the panel becomes a disclosure under the bar ────────── */
@media (max-width: 859px) {
  .bx-shell { gap: 8px; padding: 8px 16px; }
  .bx-brand { font-size: 18px; }
  .bx-menu { display: inline-flex; }
  .bx-shell[data-bx-ready] .bx-panel { display: none; }
  /* The open panel: the nav list fills the first row, then the language
     and scheme switches share ONE row beneath it (about 290 px together,
     inside the 358 px of a 390 px phone). */
  .bx-shell[data-bx-open] .bx-panel {
    order: 10;
    flex: 1 0 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 6px 0 8px;
    border-top: 1px solid var(--bx-line);
  }
  .bx-shell[data-bx-open] .bx-nav { flex: 1 0 100%; }
  .bx-shell[data-bx-open] .bx-nav-list { flex-direction: column; gap: 4px; }
  .bx-shell[data-bx-open] .bx-nav-link { min-height: 44px; padding: 0 14px; border-radius: 12px; }
  .bx-shell[data-bx-open] .bx-switch { min-height: 44px; }
  .bx-shell[data-bx-open] .bx-seg { min-height: 36px; }
  .bx-signin { padding: 0 14px; }
  /* The open panel takes its own row BELOW the bar, and it comes before the
     account button in the DOM, so the account button follows it onto the
     last row: what you see top-to-bottom is what Tab visits (WCAG 2.4.3). */
  .bx-shell[data-bx-open] .bx-signin { order: 11; flex: 1 0 100%; min-height: 44px; }
}
@media (max-width: 359px) {
  .bx-shell { padding: 8px 12px; }
  .bx-brand::before { width: 26px; height: 26px; }
  .bx-menu { padding: 0 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .bx-nav-link,
  .bx-seg,
  .bx-menu,
  .bx-menu::after { transition: none; }
}

@media (forced-colors: active) {
  .bx-nav-link[aria-current="page"] { outline: 2px solid CanvasText; }
  .bx-brand::before { forced-color-adjust: none; }
  /* System colours replace the accent fill, so the current segment keeps
     a visible fill of its own. */
  .bx-seg[aria-checked="true"],
  .bx-seg[aria-checked="true"]:hover {
    forced-color-adjust: none;
    background: Highlight;
    color: HighlightText;
  }
}
