/* ============================================================
   OPAL marketing site (opal.buzz)
   One set of CSS custom properties drives the whole site.

   Ported in shape from the Reflex site (reflex.rehab,
   styles/reflex.css), which was itself ported from the ATDev
   design system, so anyone who can work on one can work on all
   three. Typography is the ATDev family set (Montserrat,
   Raleway). The brand tokens are retuned to OPAL: ATDev Deep
   Blue and Reflex Blue carry the accent, with Teal and a violet
   standing in for the play-of-color an opal actually has. The
   shimmer only ever appears in fills and gradients, never behind
   body text.

   Light is the default; a dark theme overrides the tokens.

   This is the site for an accessibility project, so the
   accessibility rules here are load-bearing, not decoration:
     - every interactive target is at least 48px in its smaller
       axis, because this site is read by people using head
       trackers, eye gaze and switch scanning
     - :focus-visible is always drawn and never removed
     - every animation is inside a prefers-reduced-motion guard
     - text contrast is AA or better in both themes
   Do not "clean up" any of those without reading docs/accessibility.md.
   ============================================================ */

:root {
  /* palette */
  --bg: #F9FAFB;
  --bg-2: #FFFFFF;
  --bg-3: #EEF4F8;
  --surface: rgba(3, 9, 13, 0.03);
  --surface-2: rgba(3, 9, 13, 0.06);
  --line: rgba(3, 9, 13, 0.10);
  --line-2: rgba(3, 9, 13, 0.18);

  --text: #03090D;
  --muted: #4B5563;
  --faint: #606161;

  /* OPAL brand tokens.
     --brand is the accent used for text, icons and links, so it shifts
     per theme to stay >= AA (Deep Blue #115C90 is 6.6:1 on the off-white
     page). --brand-fill, --brand-soft, --brand-teal and --brand-violet are
     fixed brand values for fills, gradients and graphics, where contrast
     is not a text concern. Never set body copy in --brand-fill or
     --brand-violet on a light ground; both fail AA. */
  --brand: #115C90;
  --brand-deep: #0D466E;
  --brand-fill: #22A9FF;
  --brand-soft: #93C0DB;
  --brand-teal: #176E76;
  --brand-violet: #7C5CFF;
  --brand-navy: #174678;

  --brand-rgb: 17, 92, 144;
  --brand-fill-rgb: 34, 169, 255;
  --brand-teal-rgb: 23, 110, 118;
  --brand-violet-rgb: 124, 92, 255;
  --brand-soft-rgb: 147, 192, 219;

  /* The opal itself: three stops, teal to blue to violet. Used for fills,
     rules and graphics. --grad-ink is the darkened variant for text that
     gets background-clipped, so clipped headings still pass AA. */
  --grad: linear-gradient(135deg, #176E76 0%, #22A9FF 55%, #7C5CFF 100%);
  --grad-soft: linear-gradient(135deg, rgba(23, 110, 118, .10), rgba(34, 169, 255, .10) 55%, rgba(124, 92, 255, .12));
  --grad-ink: linear-gradient(135deg, #0F5A61 0%, #115C90 55%, #5B3FD6 100%);
  /* Accent rules drawn as a background layer instead of a clipped ::before.
     A pseudo element needs overflow: hidden on its parent to follow the
     corner radius, and overflow: hidden would also clip the focus ring of
     anything focusable inside. On this site a clipped focus ring is a
     removed focus ring, so the accent is a background and the radius clips
     it for free. */
  --grad-line: linear-gradient(90deg, rgba(23, 110, 118, .82), rgba(34, 169, 255, .82) 55%, rgba(124, 92, 255, .82));
  --grad-edge: linear-gradient(180deg, #176E76, #22A9FF 55%, #7C5CFF);

  --ok: #1B7F4B;
  --warn: #8A5A00;

  --radius: 14px;
  --radius-sm: 10px;
  --radius-lg: 24px;
  --radius-pill: 999px;
  --container: 1180px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* Minimum hit target. 48px, not 44px: the CSS box is what a head
     tracker or a gaze pointer has to hold still inside. */
  --target: 48px;

  --font: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-body: "Raleway", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --shadow-sm: 0 1px 2px rgba(3, 9, 13, .05);
  --shadow: 0 1px 2px rgba(3, 9, 13, .04), 0 10px 28px rgba(3, 9, 13, .07);
  --shadow-lg: 0 2px 4px rgba(3, 9, 13, .05), 0 22px 56px rgba(3, 9, 13, .12);

  --nav-bg: rgba(255, 255, 255, 0.84);
  --nav-bg-solid: rgba(255, 255, 255, 0.97);
  --grid-line: rgba(3, 9, 13, 0.06);

  color-scheme: light;
}

/* ============ DARK THEME ============
   Light is the default. The dark palette activates when data-theme="dark"
   is set on <html>, by the no-FOUC head script and by the nav toggle.
   --brand brightens to a light blue so accent text stays legible on
   near-black. */
:root[data-theme="dark"] {
  --bg: #03090D;
  --bg-2: #0A1219;
  --bg-3: #0E1922;
  --surface: rgba(255, 255, 255, 0.035);
  --surface-2: rgba(255, 255, 255, 0.06);
  --line: rgba(255, 255, 255, 0.11);
  --line-2: rgba(255, 255, 255, 0.20);

  --text: #F9FAFB;
  --muted: #B4BFC9;
  --faint: #98A3AE;

  --brand: #6CC5FF;
  --brand-deep: #22A9FF;
  --brand-soft: #A9CFE6;

  --grad-ink: linear-gradient(135deg, #67D6DE 0%, #6CC5FF 55%, #B79BFF 100%);

  --ok: #56D364;
  --warn: #E3B341;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .6);
  --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 28px rgba(0, 0, 0, .45);
  --shadow-lg: 0 2px 4px rgba(0, 0, 0, .5), 0 22px 56px rgba(0, 0, 0, .55);

  --nav-bg: rgba(3, 9, 13, 0.80);
  --nav-bg-solid: rgba(3, 9, 13, 0.97);
  --grid-line: rgba(255, 255, 255, 0.05);

  color-scheme: dark;
}

/* Windows High Contrast and forced-colors: let the OS win outright. */
@media (forced-colors: active) {
  .btn, .card, .nav, .card__icon, .card__tag, .shot__frame, .video__frame { border: 1px solid; }
  /* The play control is a translucent scrim over a picture, and a forced
     palette drops the scrim. Give it a real border and a solid ground so it
     is still visibly a control, which is rule 10. */
  .video__play { background: Canvas; border: 1px solid; }
  .video__label { background: transparent; color: CanvasText; }
  .grad-text {
    background: none !important;
    -webkit-text-fill-color: currentColor !important;
    color: LinkText !important;
  }
}

/* ============ BASE ============ */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Anchors must not land under the sticky nav. */
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: var(--font);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 .5em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.25rem, 1.4rem + 3.6vw, 4rem); }
h2 { font-size: clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem); }
h3 { font-size: clamp(1.2rem, 1.05rem + .6vw, 1.5rem); }
h4 { font-size: 1.0625rem; }

p { margin: 0 0 1.15em; max-width: 68ch; }
p:last-child { margin-bottom: 0; }

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }

strong { font-weight: 700; color: var(--text); }
small { font-size: .875rem; }

img, svg, video { max-width: 100%; height: auto; display: block; }

hr { border: 0; height: 1px; background: var(--line); margin: 3rem 0; }

code, kbd {
  overflow-wrap: anywhere;
  font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
  font-size: .9em;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: .1em .4em;
}

/* ============ FOCUS AND SKIP LINK ============
   Never remove these. They are the whole point of the project. */
:focus-visible {
  outline: 3px solid var(--brand-fill);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  /* Padding alone landed near 46px, just under the 48px floor that
     docs/accessibility.md sets. Make it explicit rather than emergent. */
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  position: absolute;
  left: 1rem;
  top: -100px;
  z-index: 200;
  background: var(--bg-2);
  color: var(--text);
  border: 2px solid var(--brand);
  border-radius: var(--radius-sm);
  padding: .85rem 1.25rem;
  font-family: var(--font);
  font-weight: 600;
  text-decoration: none;
  transition: top .15s var(--ease);
}
.skip-link:focus { top: 1rem; }

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

/* ============ LAYOUT ============ */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

.section { padding-block: clamp(3.5rem, 7vw, 6.5rem); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }
.section--alt { background: var(--bg-2); border-block: 1px solid var(--line); }
.section--grad { background: var(--grad-soft); border-block: 1px solid var(--line); }

.section-head { max-width: 46rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center p { margin-inline: auto; }

.eyebrow {
  font-family: var(--font);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 0 0 .9rem;
  display: flex;
  align-items: center;
  gap: .65rem;
}
/* A short gradient rule in front of the label. Decoration only: the word
   is the label, and a reader that ignores the pseudo-element loses nothing. */
.eyebrow::before {
  content: "";
  width: 1.75rem;
  height: 3px;
  border-radius: 3px;
  background: var(--grad);
  flex: none;
}
.section-head--center .eyebrow { justify-content: center; }

.lead {
  font-size: clamp(1.1rem, 1rem + .5vw, 1.35rem);
  line-height: 1.55;
  color: var(--muted);
}

.grad-text {
  background: var(--grad-ink);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

.grid { display: grid; gap: clamp(1rem, 2.2vw, 1.75rem); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
/* Exactly three items. auto-fit would turn a trio into two plus an orphan on
   a tablet, so a trio goes straight from one column to three. Below the
   three-column breakpoint the cards inside it drop their box and become a
   flush list, which is the SMALL SCREENS section further down. */
.grid--trio { grid-template-columns: 1fr; }
@media (min-width: 62rem) {
  .grid--trio { grid-template-columns: repeat(3, 1fr); }
}
.split {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
  align-items: start;
}

/* ============ NAV ============ */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--nav-bg);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--line);
}
@supports not (backdrop-filter: blur(1px)) {
  .nav { background: var(--nav-bg-solid); }
}

.nav__inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 72px;
}

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-family: var(--font);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: -.01em;
  color: var(--text);
  text-decoration: none;
  padding: .5rem .25rem;
  min-height: var(--target);
}
.nav__mark { width: 28px; height: 28px; flex: none; }

/* Product mark and parent-company mark as one group. The auto margin lives
   here rather than on .nav__brand so that hiding the ATDev mark at narrow
   widths cannot take the layout's left anchor with it. */
.nav__lockup {
  display: flex;
  align-items: center;
  gap: .35rem;
  margin-right: auto;
  min-width: 0;
}

/* ATDev, the parent company. A separate link rather than something nested in
   .nav__brand, because that link points at this site's root and this one
   points off-site, and a link inside a link is invalid and unreachable.
   The mark is inline SVG, not an <img>, because its dark half is filled with
   var(--text) and its letters with var(--bg): on the light theme that is the
   logo as drawn, and on the dark theme it inverts rather than disappearing
   into a page whose background is the same near-black. The blue half is a
   fixed brand value and carries its own ground in both themes. */
.nav__parent {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  flex: none;
  min-height: var(--target);
  padding: .5rem 0 .5rem .85rem;
  margin-left: .35rem;
  border-left: 1px solid var(--line);
  color: var(--faint);
  text-decoration: none;
}
.nav__parent:hover { color: var(--text); text-decoration: none; }
.nav__by {
  font-family: var(--font);
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.nav__atdev { width: 62px; height: auto; flex: none; display: block; }
/* Below the three-column header width the row is brand, parent mark and two
   48px buttons inside a 320px viewport. The word goes first, then the mark
   narrows; both are redundant with the footer, which names ATDev in text. */
@media (max-width: 600px) {
  .nav__by { display: none; }
  .nav__atdev { width: 50px; }
  .nav__parent { padding-left: .6rem; margin-left: .2rem; }
}

.nav__links {
  display: flex;
  align-items: center;
  gap: .25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding: 0 .95rem;
  border-radius: var(--radius-sm);
  font-family: var(--font);
  font-size: .95rem;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
}
.nav__link:hover { color: var(--text); background: var(--surface); }
.nav__link[aria-current="page"] { color: var(--brand); background: var(--surface); }

.nav__actions { display: flex; align-items: center; gap: .5rem; }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--target);
  height: var(--target);
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  color: var(--text);
  cursor: pointer;
}
.icon-btn:hover { border-color: var(--line-2); background: var(--surface); }
.icon-btn svg { width: 20px; height: 20px; }

.nav__toggle { display: none; }

/* The theme toggle ships both glyphs in the markup, so the swap costs no
   request and cannot flash the wrong one. */
:root:not([data-theme="dark"]) .icon-sun { display: none; }
:root[data-theme="dark"] .icon-moon { display: none; }

@media (max-width: 860px) {
  .nav__toggle { display: inline-flex; }
  .nav__links {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: .25rem;
    padding: .75rem clamp(1.25rem, 4vw, 2.5rem) 1.25rem;
    background: var(--nav-bg-solid);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow);
  }
  .nav__links[hidden] { display: none; }
  .nav__link { justify-content: flex-start; padding: 0 1rem; }
}

/* ============ BUTTONS ============ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  min-height: var(--target);
  padding: .8rem 1.7rem;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font);
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: .01em;
  text-decoration: none;
  cursor: pointer;
  transition: transform .15s var(--ease), box-shadow .15s var(--ease), background-color .15s var(--ease);
}
.btn:hover { text-decoration: none; }
.btn svg { width: 18px; height: 18px; flex: none; }

.btn--primary {
  background: var(--brand);
  color: #fff;
  box-shadow: var(--shadow);
}
.btn--primary:hover {
  background: var(--brand-deep);
  transform: translateY(-1px);
  box-shadow: var(--shadow-lg);
}
:root[data-theme="dark"] .btn--primary { color: #03090D; }

.btn--ghost {
  background: var(--bg-2);
  color: var(--text);
  border-color: var(--line-2);
}
.btn--ghost:hover { border-color: var(--brand); color: var(--brand); background: var(--surface); }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }

/* ============ HERO ============ */
.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.5rem, 8vw, 7rem) clamp(3rem, 6vw, 5.5rem);
  background:
    radial-gradient(58rem 30rem at 78% -12%, rgba(124, 92, 255, .20), transparent 62%),
    radial-gradient(46rem 26rem at 46% -18%, rgba(34, 169, 255, .16), transparent 60%),
    radial-gradient(52rem 30rem at 4% 2%, rgba(23, 110, 118, .18), transparent 62%),
    var(--bg);
}

.hero::after {
  /* Faint grid, purely decorative. */
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(70% 60% at 50% 0%, #000 30%, transparent 100%);
  -webkit-mask-image: radial-gradient(70% 60% at 50% 0%, #000 30%, transparent 100%);
  pointer-events: none;
}

.hero > .container { position: relative; z-index: 1; }
/* Was 20ch, which was the measure for a headline sitting alone above an empty
   right half. It is wider now because the only width this value still governs
   is the stacked tablet range: under 40rem and from 62rem up, the two blocks
   at the end of this file set their own. */
.hero h1 { max-width: 26ch; }
.hero .lead { max-width: 40rem; }
.hero__note { margin-top: 2.25rem; font-size: .95rem; color: var(--faint); }

/* The hero is two columns from 62rem up, copy left and the lead film right.
   Before this it was one column of text, which left the right half of a
   desktop window empty and pushed the film into a section of its own below the
   fold. 62rem is the width at which the container can give a 16:9 frame a
   useful size without squeezing the headline under about twenty characters a
   line; under it the two stack, which is the only thing that works on a phone.
   The media track is the wider of the two because a film that is much shorter
   than the copy beside it just moves the empty space from the right of the
   hero to above and below the frame. */
@media (min-width: 62rem) {
  .hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
    gap: clamp(2rem, 3.5vw, 3rem);
    align-items: center;
  }
  /* The global h1 clamp assumes a headline with the whole container to itself.
     It is already at 58px when this breakpoint lands, which in half the width
     puts "wheelchairs" on a line of its own. The grid track is the measure
     now, so the size comes down to suit it. */
  .hero h1 { font-size: clamp(2.4rem, .9rem + 2.6vw, 3.25rem); max-width: 100%; }
  .hero .lead { max-width: 100%; }
  /* Full width under both columns, with a rule above it. It is a footnote
     about the team rather than part of the pitch, and running it under the
     film as well as the copy is what squares the bottom of the hero off. */
  .hero__note {
    grid-column: 1 / -1;
    /* The row gap already sets it off the copy, and the 68ch cap every p
       carries would stop the rule short of the film and leave it hanging in
       the middle of the hero. */
    max-width: none;
    margin-top: 0;
    padding-top: 1.6rem;
    border-top: 1px solid var(--line);
  }
}

/* ============ BADGES AND STATUS ============ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 34px;
  padding: .4rem .95rem;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  background: var(--bg-2);
  box-shadow: var(--shadow-sm);
  font-family: var(--font);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1.5rem;
}
.badge__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--grad); flex: none; }

/* The honest-status band. It is an asset on this site, not an apology, so it
   is built to be read rather than tucked away: full gradient edge, its own
   surface, and a heading in the display face. */
.status-band {
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  background-color: var(--bg-2);
  background-image: var(--grad-edge);
  background-repeat: no-repeat;
  background-size: 5px 100%;
  background-position: left top;
  box-shadow: var(--shadow-sm);
  padding: 1.4rem 1.6rem 1.4rem 2.1rem;
}
.status-band h3 { font-size: 1.1rem; margin-bottom: .4rem; }
.status-band p { color: var(--muted); font-size: .98rem; }

/* ============ CARDS ============
   A card is a bordered surface with a gradient hairline along its top edge.
   That hairline is the only place the opal gradient touches a card, which
   keeps a grid of them calm and still ties them to the brand. */
.card {
  position: relative;
  background-color: var(--bg-2);
  background-image: var(--grad-line);
  background-repeat: no-repeat;
  background-size: 100% 3px;
  background-position: top left;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 2.4vw, 1.9rem);
  box-shadow: var(--shadow);
}
.card h3 { margin-bottom: .5rem; }
.card p { color: var(--muted); font-size: .98rem; }

/* The icon tile carries the gradient as a fill, never behind text. The glyph
   flips to near-black in the dark theme because --grad-ink inverts with the
   theme, which is the same trick .btn--primary uses. Every glyph is
   aria-hidden, so the tile is reinforcement and never the only cue. */
.card__icon {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  background: var(--grad-ink);
  color: #fff;
  margin-bottom: 1.15rem;
  flex: none;
}
:root[data-theme="dark"] .card__icon { color: #03090D; }
.card__icon svg { width: 23px; height: 23px; }

/* Status chips. The credibility of this site rests on saying plainly which
   pieces exist, so status is a chip rather than a line of grey caps. The dot
   is never the only cue: the words carry the meaning, per rule 5 of
   docs/accessibility.md. */
.card__tag {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-top: 1.15rem;
  padding: .32rem .75rem .32rem .6rem;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-family: var(--font);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
}
.card__tag::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--faint);
  flex: none;
}
.card__tag--live {
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 45%, transparent);
}
.card__tag--live::before { background: var(--ok); }

/* A footnote rather than a status. Same family, no chip. */
.card__note {
  display: block;
  margin-top: 1.15rem;
  font-family: var(--font);
  font-size: .8rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--faint);
}

/* A card that links somewhere. The whole card is the target, which matters
   on a site people navigate by gaze or by switch scanning. */
.card--link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform .15s var(--ease), box-shadow .15s var(--ease), border-color .15s var(--ease);
}
.card--link:hover {
  border-color: var(--brand);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

/* ============ DIAGRAMS ============
   Inline SVG only, so there is nothing to fetch and nothing the CSP has to
   allow. Every colour comes from a token, so the diagrams re-theme with the
   page instead of carrying a baked-in ground. Text inside a diagram is never
   the only place an idea appears: the prose beside it says the same thing, so
   a screen reader that skips the graphic loses nothing. */
.diagram {
  display: block;
  width: 100%;
  height: auto;
  margin-top: 1.6rem;
  /* Without a floor the SVG shrinks to the viewport and its labels scale with
     it: at 360px the 15px text lands near 6px, which is unreadable and absurd
     on this site in particular. The floor makes .figure scroll instead. */
  min-width: 42rem;
}
.diagram__head {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 700;
  fill: var(--text);
}
.diagram__label { font-family: var(--font-body); font-size: 15px; fill: var(--muted); }
.diagram__note  { font-family: var(--font-body); font-size: 13px; font-weight: 600; fill: var(--brand); }
.diagram__bar   { fill: var(--brand-fill); }
.diagram__bar--weak { fill: var(--line-2); }
.diagram__band  { fill: var(--brand-fill); opacity: .12; }
.diagram__rule  { stroke: var(--brand); stroke-width: 1.5; fill: none; }
.diagram__box   { fill: var(--bg-2); stroke: var(--line-2); stroke-width: 1.5; }
.diagram__flow  { stroke: var(--line-2); stroke-width: 1.5; fill: none; }
.diagram__pill  { fill: var(--surface); stroke: var(--line-2); stroke-width: 1; }
.diagram__small { font-family: var(--font-body); font-size: 12.5px; fill: var(--faint); }
.diagram__tag   { font-family: var(--font); font-size: 11px; font-weight: 700; letter-spacing: .09em; fill: var(--faint); }
.diagram__sub   { font-family: var(--font-body); font-size: 14px; fill: var(--muted); }
.diagram__arrow { fill: var(--line-2); }

/* A diagram is wide by nature. Let it scroll inside its own box on a narrow
   screen so the page body never scrolls sideways. */
.figure {
  margin-top: 2rem;
  overflow-x: auto;
}
.figure figcaption {
  color: var(--faint);
  font-size: .9rem;
  margin-top: .85rem;
}
/* A region that scrolls has to be reachable without a pointer, so both of the
   scrollers carry tabindex="0". The global focus ring shows where you are. */
.figure:focus-visible, .table-wrap:focus-visible { outline-offset: 4px; }
.figure__hint {
  display: none;
  color: var(--faint);
  font-size: .85rem;
  margin-top: .6rem;
}
@media (max-width: 46rem) {
  .figure__hint { display: block; }
}

/* ============ STATS ============
   A figure and the sentence that gives it meaning. This site describes a
   barrier most readers have never hit, so the numbers carry the job of
   establishing that it is large before any solution is named. Display
   weight Montserrat, clipped through --grad-ink like the other display
   type; the caption stays on --muted so it holds AA on both grounds. */
/* Selector is .stat > .stat__figure, not .stat__figure: the caption rule
   below is (0,1,1) and a bare class is (0,1,0), so the plain version lost
   and every figure rendered at caption size. */
.stat > .stat__figure {
  font-family: var(--font);
  font-size: clamp(2.4rem, 5.4vw, 3.4rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.02em;
  margin: 0 0 .4rem;
}
.stat p { color: var(--muted); font-size: .98rem; }

/* ============ FEATURE LIST ============ */
.checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
.checklist li {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: .85rem;
  align-items: start;
  color: var(--muted);
}
.checklist svg { width: 24px; height: 24px; color: var(--brand); margin-top: .15rem; }
.checklist strong { display: block; color: var(--text); font-family: var(--font); }

/* ============ TIMELINE ============ */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline > li {
  display: grid;
  grid-template-columns: 3.25rem 1fr;
  gap: clamp(1rem, 2vw, 1.75rem);
  padding-bottom: 2.25rem;
  position: relative;
}
.timeline > li::before {
  /* The rail. Sits behind the marker, stops at the last item. */
  content: "";
  position: absolute;
  left: 1.6rem;
  top: 3.25rem;
  bottom: 0;
  width: 2px;
  background: var(--line);
}
.timeline > li:last-child { padding-bottom: 0; }
.timeline > li:last-child::before { display: none; }

.timeline__marker {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  font-family: var(--font);
  font-weight: 700;
  font-size: .95rem;
  color: var(--brand);
  position: relative;
  z-index: 1;
}
.timeline__body h3 { margin-bottom: .35rem; padding-top: .55rem; }
.timeline__body p { color: var(--muted); }

/* ============ TABLE ============ */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
}
table { width: 100%; border-collapse: collapse; font-size: .96rem; }
th, td { text-align: left; padding: .95rem 1.15rem; border-bottom: 1px solid var(--line); vertical-align: top; }
th {
  font-family: var(--font);
  font-size: .82rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
}
tbody tr:last-child td { border-bottom: 0; }
td strong { font-family: var(--font); }

/* ============ QUOTE ============ */
.quote {
  margin: 0;
  position: relative;
  padding: clamp(1.5rem, 3vw, 2.5rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
  box-shadow: var(--shadow);
}
/* A left double quotation mark, written as its CSS escape. The file used
   to hold a stray U+0081 control character followed by a literal C, which
   drew a giant translucent letter C over every pull quote. It is pure
   decoration either way: the blockquote reads as a quote without it. */
.quote::before {
  content: "\201C";
  position: absolute;
  top: .06em; left: .2em;
  font-family: var(--font);
  font-size: 5.5rem;
  line-height: 1;
  color: var(--brand-fill);
  opacity: .18;
  pointer-events: none;
}
.quote p { font-size: clamp(1.2rem, 1rem + .8vw, 1.65rem); line-height: 1.45; font-weight: 500; }
.quote figcaption { color: var(--faint); font-size: .92rem; font-family: var(--font); }
/* A pull quote that sits under a .split rather than inside one. */
.quote--wide { margin-top: clamp(2rem, 4vw, 3rem); }

/* A spoken instruction, shown as an example of input. The dashed edge keeps
   it visibly distinct from .quote, which is for what a person said about the
   project rather than what a person says to the editor. */
.say {
  margin: 1.1rem 0;
  padding: 1.1rem 1.25rem;
  border: 1px dashed var(--line-2);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 1.05rem;
  line-height: 1.5;
  font-weight: 500;
  color: var(--text);
  max-width: none;
}

/* ============ SCREENSHOT ============
   A framed application window. The bar is a window chrome affordance and its
   label is real text, not decoration, so it is a <b> and not a pseudo
   element. The image still carries full alt text: rule 6 of
   docs/accessibility.md says every image is labelled or hidden, and this one
   is the first meaningful photograph-shaped thing on the site. */
.shot { margin: 0; }
.shot__frame {
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  background: var(--bg-3);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.shot__bar {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .65rem .9rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.shot__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--line-2);
  flex: none;
}
.shot__title {
  margin-left: .6rem;
  font-family: var(--font);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--faint);
}
.shot img { width: 100%; }
.shot figcaption {
  margin-top: .95rem;
  color: var(--faint);
  font-size: .9rem;
  line-height: 1.55;
}

/* ============ VIDEO ============
   A click-to-load facade, not an embed. The poster is a local file and the
   control over it is an ordinary link to youtube.com, so a page that never
   runs JavaScript is still a page where the film plays (rule 7 of
   docs/accessibility.md). Where the swap is available, scripts/opal.js
   replaces that link with a button that loads the player inline, from
   youtube-nocookie.com and only once someone presses it. Nothing is
   requested from a third party before that press, which is the point of
   doing it this way on this site: the visitors this project exists for
   should not have to load a player they never asked for. The one CSP
   allowance it needs is in netlify.toml.

   The whole poster is the target, which clears the 48px floor by a wide
   margin, and the label is real text under the play glyph rather than a
   triangle on its own. */
.video { margin: 0; }
.video__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  background: var(--bg-3);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.video__frame img,
.video__frame iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
}
/* Styles the shipped <a> and the <button> that replaces it, identically. */
.video__play {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .85rem;
  width: 100%;
  padding: 1rem;
  border: 0;
  background: rgba(3, 9, 13, .42);
  font-family: var(--font);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s var(--ease);
}
.video__play:hover { background: rgba(3, 9, 13, .26); }
/* The ring is drawn inside the frame rather than outside it, because the
   frame clips its overflow. It is never removed. */
.video__play:focus-visible { outline-offset: -7px; }
.video__glyph {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--brand-fill);
  color: #03090D;
}
.video__glyph svg { width: 26px; height: 26px; margin-left: 4px; }
/* A solid chip rather than white text on the scrim alone. The scrim sits over
   whichever frame the poster happens to be, so it cannot be relied on for
   contrast; the chip holds white text at AA however bright the picture under
   it is. */
.video__label {
  padding: .5rem 1rem;
  border-radius: var(--radius-pill);
  background: rgba(3, 9, 13, .78);
  color: #fff;
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: .01em;
}
/* Kept, but no page uses one: both films had their captions removed on
   2026-08-25 and now carry only their poster alt text and their play label.
   This is here so a caption added later is styled rather than unstyled. */
.video figcaption {
  margin-top: .95rem;
  color: var(--faint);
  font-size: .9rem;
  line-height: 1.55;
}
/* A media block that follows a .split rather than sitting inside one, the
   same role .quote--wide plays. Capped so a 16:9 frame does not tower over
   the prose it belongs to. */
.video--wide {
  max-width: 46rem;
  margin: clamp(2rem, 4vw, 3rem) auto 0;
}
/* The lead film. It sits inside the hero, in the right-hand grid track from
   62rem up and under the copy below that, so its width is the track's or the
   container's rather than its own. The cap only matters in the stacked case on
   a wide tablet, where a 16:9 frame running the full container would push the
   whole hero off the first screen. */
.video--feature {
  max-width: 46rem;
  margin-inline: auto;
}
/* At phone widths the label is wider than the usable line inside the frame, so
   it wraps and a stadium-shaped chip on two lines reads as a mistake. Shrink
   the control to keep the label on one line, and fall back to the standard
   radius so that if it does wrap it still looks deliberate. The target is the
   whole poster, not the glyph, so shrinking the glyph costs nothing against the
   48px floor. */
@media (max-width: 30rem) {
  .video__play { gap: .6rem; padding: .75rem; }
  .video__glyph { width: 56px; height: 56px; }
  .video__glyph svg { width: 21px; height: 21px; margin-left: 3px; }
  .video__label {
    padding: .45rem .8rem;
    border-radius: var(--radius);
    font-size: .85rem;
  }
}

/* A card that follows a .split inside the same container, rather than sitting
   in one. Same role .quote--wide and .video--wide play. */
.card--after-split { margin-top: clamp(2rem, 4vw, 3rem); }

/* ============ CTA ============ */
.cta {
  background: var(--grad);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: clamp(2rem, 5vw, 3.5rem);
  text-align: center;
}
.cta h2 { color: #fff; }
.cta p { color: rgba(255, 255, 255, .92); margin-inline: auto; }
.cta .btn--primary { background: #fff; color: #0D466E; }
.cta .btn--primary:hover { background: #EEF4F8; }
.cta .btn--ghost { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .55); }
.cta .btn--ghost:hover { background: rgba(255, 255, 255, .12); color: #fff; border-color: #fff; }
.cta .btn-row { justify-content: center; }
.cta :focus-visible { outline-color: #fff; }

/* ============ FORMS ============ */
.form { display: grid; gap: 1.25rem; max-width: 38rem; }
.field { display: grid; gap: .45rem; }
.field label { font-family: var(--font); font-weight: 600; font-size: .95rem; }
.field .hint { color: var(--faint); font-size: .88rem; }

input[type="text"], input[type="email"], select, textarea {
  width: 100%;
  min-height: var(--target);
  padding: .75rem .9rem;
  font: inherit;
  font-size: 1rem;
  color: var(--text);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
}
textarea { min-height: 9rem; resize: vertical; }
input:hover, select:hover, textarea:hover { border-color: var(--brand-soft); }

fieldset { border: 1px solid var(--line); border-radius: var(--radius); padding: 1.15rem 1.35rem 1.35rem; margin: 0; }
legend { font-family: var(--font); font-weight: 600; font-size: .95rem; padding-inline: .35rem; }

/* Checkbox rows are full width so the label is part of the target. */
.check {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: .75rem;
  align-items: center;
  min-height: var(--target);
  padding: .25rem .35rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.check:hover { background: var(--surface); }
.check input { width: 24px; height: 24px; accent-color: var(--brand); margin: 0; }

/* Honeypot. Hidden from people, reachable by bots. */
.hp { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }

/* ============ FOOTER ============ */
.footer {
  background: var(--bg-2);
  border-top: 1px solid var(--line);
  padding-block: clamp(2.5rem, 5vw, 4rem) 2rem;
  font-size: .95rem;
}
.footer__grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  margin-bottom: 2.5rem;
}
.footer h4 {
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text);
  margin-bottom: .75rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--line);
}
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
/* 48px, not the 40px this used to be. docs/accessibility.md listed the
   footer as the one place the site broke its own target-size floor, on the
   grounds that widening the rows fragmented the block. Dropping the row
   border and letting the columns breathe instead keeps the block reading as
   a list at the full target height. */
.footer a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-inline: .55rem;
  margin-inline: -.55rem;
  border-radius: var(--radius-sm);
  color: var(--muted);
  text-decoration: none;
}
.footer a:hover { color: var(--brand); background: var(--surface); text-decoration: underline; }
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
  color: var(--faint);
  font-size: .9rem;
}
.footer__brand { display: flex; align-items: center; gap: .6rem; font-family: var(--font); font-weight: 700; color: var(--text); }
.footer__brand svg { width: 24px; height: 24px; }

/* ============ MOTION ============
   Every transition and animation on this site is opt-in. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .card--link:hover, .btn--primary:hover { transform: none; }
}

/* ============ ACRONYM ============
   OPAL is set in caps, which makes readers ask what it stands for. Marking
   the letters answers that at first mention. The capitals carry the meaning
   on their own, so the colour is reinforcement and never the only cue, which
   is the rule the rest of this stylesheet follows too. */
.acro b {
  font-weight: 700;
  font-style: normal;
  color: var(--brand);
}

/* ============ STAT BAND ============
   Three numbers reading as one instrument panel, ruled off from the prose
   above and below, so the section does not read as a fourth card grid. */
.stat-band {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(1.75rem, 3.5vw, 2.5rem);
  margin-bottom: clamp(1.75rem, 4vw, 2.75rem);
}
@media (min-width: 62rem) {
  .stat-band .stat + .stat {
    border-left: 1px solid var(--line);
    padding-left: clamp(1rem, 2.5vw, 2rem);
  }
}
/* Stacked, the three numbers need a rule between them or they read as one
   run-on paragraph. The trio gap is zero below the breakpoint, so the
   padding here supplies the rhythm. */
@media (max-width: 61.999rem) {
  .stat-band .stat { padding-block: 1.35rem; }
  .stat-band .stat + .stat { border-top: 1px solid var(--line); }
  .stat-band .stat:first-child { padding-top: .35rem; }
  .stat-band .stat:last-child { padding-bottom: .35rem; }
}

/* ============ MOTION ============
   All CSS. scripts/opal.js stays the theme toggle, the nav disclosure and the
   footer year, and nothing else goes in it. The hero animation runs once on
   load. The scroll reveal is progressive enhancement: a browser without
   animation-timeline renders everything static, which is a perfectly good
   outcome. Both are inside prefers-reduced-motion: no-preference, because a
   view() timeline ignores animation-duration, so the global reduce rule alone
   could strand an element at opacity 0 and hide the content outright. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes rise {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }
  .hero .badge,
  .hero h1,
  .hero .lead,
  .hero .btn-row,
  .hero__note { animation: rise .55s var(--ease) both; }
  .hero h1       { animation-delay: .06s; }
  .hero .lead    { animation-delay: .12s; }
  .hero .btn-row { animation-delay: .18s; }
  .hero__note    { animation-delay: .3s; }

  /* The film gets its own curve rather than a slot in the rise sequence. It is
     the only block in the hero that is a picture, and settling it in from just
     under size reads as a frame arriving rather than as more text landing. */
  @keyframes settle {
    from { opacity: 0; transform: translateY(16px) scale(.97); }
    to   { opacity: 1; transform: none; }
  }
  .hero__media { animation: settle .7s var(--ease) both .14s; }

  /* One slow ring off the play control, looping. A poster with a static button
     on it gives no signal that there is a film behind it, and this is the only
     thing in the hero worth pressing. It is a pseudo-element so it never
     touches the 72px target or the focus ring, and it is scoped to the hero
     film: the mission film further down the page is track record rather than
     an invitation, and a second pulsing ring would just compete with this one. */
  @keyframes play-ring {
    0%   { transform: scale(1); opacity: .5; }
    70%  { transform: scale(1.75); opacity: 0; }
    100% { transform: scale(1.75); opacity: 0; }
  }
  .video--feature .video__glyph::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid var(--brand-fill);
    animation: play-ring 3s var(--ease) infinite;
  }

  @supports (animation-timeline: view()) {
    .section-head, .figure, .card, .stat, .quote, .status-band, .shot {
      animation: rise .6s var(--ease) both;
      animation-timeline: view();
      animation-range: entry 0% entry 42%;
    }
  }
}

/* ============ SMALL SCREENS ============
   The site has one real breakpoint at 860px and it only rearranges the nav.
   These are the places where the desktop values do not survive a phone. */
/* Three bordered boxes stacked on a phone is most of a screen of scroll for
   three short ideas, and each box spends sixty vertical pixels on an icon
   sitting alone above its heading. Below the three-column breakpoint a trio
   drops the box: the icon moves beside the heading, a hairline separates the
   rows, and the same three ideas fit in roughly half the height. Cards
   outside a trio, meaning every card in a .grid--2 and the ones inside a
   .split, keep their box. The :has() guard means a trio card without an icon
   degrades to a plain flush row rather than a broken two-column one. */
@media (max-width: 61.999rem) {
  .grid--trio { gap: 0; }
  .grid--trio > .card {
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 1.5rem 0;
  }
  .grid--trio > .card + .card { border-top: 1px solid var(--line); }
  .grid--trio > .card:first-child { padding-top: .25rem; }
  .grid--trio > .card:last-child { padding-bottom: .25rem; }

  .grid--trio > .card:has(> .card__icon) {
    display: grid;
    grid-template-columns: 46px 1fr;
    column-gap: 1.15rem;
    align-items: start;
  }
  .grid--trio > .card:has(> .card__icon) > .card__icon { grid-row: span 2; margin: 0; }
  .grid--trio > .card:has(> .card__icon) > h3 {
    display: flex;
    align-items: center;
    min-height: 46px;
    margin-bottom: .4rem;
  }
  .grid--trio > .card:has(> .card__icon) > p,
  .grid--trio > .card:has(> .card__icon) > .card__tag,
  .grid--trio > .card:has(> .card__icon) > .card__note { grid-column: 2; }
}

@media (max-width: 40rem) {
  .hero h1 { font-size: clamp(1.9rem, 1rem + 4.4vw, 2.6rem); max-width: 100%; }
  .stat > .stat__figure { font-size: clamp(2.1rem, 9vw, 2.6rem); }
  .quote::before { font-size: 3.5rem; }
  .quote p { font-size: 1.15rem; }
  .cta { border-radius: var(--radius); }
}

/* One button per row on a narrow phone. A full-width button is a bigger
   target for a head tracker than two half-width ones, and it stops the row
   from wrapping into a ragged pair. */
@media (max-width: 30rem) {
  .btn-row { flex-direction: column; align-items: stretch; }
  .btn-row > .btn { width: 100%; }
}

/* ============ PRINT ============ */
@media print {
  .nav, .cta, .skip-link, .footer__grid { display: none; }
  body { background: #fff; color: #000; }
  .card, .quote, .table-wrap { break-inside: avoid; box-shadow: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; color: #444; }
}
