/* stefanpressconsulting.com - the home page's release board ("mission board"), "How it's built" and the contact
   section's width. Loaded after home.css, which holds the tokens (:root) and the base look. Served as a file: the
   CSP allows no inline style. */

  :root {
    --live:  #4af0ff;   /* cyan lamp: live in production */
    --beta:  #ffc857;   /* amber lamp: in beta */
    --inuse: #a06bff;   /* violet lamp: an internal tool in daily use */
    --row:   rgba(10, 14, 26, 0.72);
    --rowhi: rgba(16, 22, 40, 0.86);
  }

  .hero { max-width: none; }   /* the headline is ~11em wide: the intro under it may use that width (owner: "wrapped funny" at 640 px) */

  /* ---- the headline v3 (owner 2026-10-24: "I need something amazing"). Line 1: a COIN that spins in place - one
     face "AI", the other "SI" - then a row of signal packets. Line 2: another row of packets and, only once the walking
     eye has reached the last of them, "engineered!" pops up with the eye dotting its i. 30 packets on line 1 and 20 on
     line 2 (owner: "make the top line have 30 dots"); 7 a row on a phone, where they cannot fit. assets/hero.js runs the sequence and staggers the landing; without it the word
     simply shows. Reduced motion: home.css stops every animation - the coin rests on "SI", the word shows, no eye.
     Screen readers hear "SI ... engineered!" (.vh copies; the drawn parts are aria-hidden). */
  .hero-title {
    margin: 22px 0 16px;
    font-size: clamp(40px, 7.4vw, 76px);          /* line 2 (25 packets + the word, ~11.8em) still fits 960 px */
    line-height: 1.02;
    letter-spacing: -0.035em;
    font-weight: 850;
    background: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: #fff;
    filter: none;
  }
  /* .hrow, not .row: home.css's .row stacks into a column on a phone (MEASURED 2026-10-24 at 375 px) */
  .hero-title .hrow { display: flex; flex-direction: row; align-items: center; white-space: nowrap; }
  .hero-title .hrow + .hrow { margin-top: 0.04em; }

  /* the coin: "AI" and "SI" stacked; assets/hero.js changes one into the other through a different mechanism each
     time (owner 2026-10-24: "rotate as a circle ... mixed up several mechanisms") - a coin flip, a full circle spin, a
     dissolve, a tumble, a glitch. Only the face with .is-on shows. Without the script: AI. Reduced motion: SI. */
  .hero-title .coin { display: inline-block; perspective: 3.2em; }
  .hero-title .coin-in { display: inline-grid; transform-style: preserve-3d; }
  .hero-title .face {
    grid-area: 1 / 1; text-align: center; opacity: 0;
    color: #fff;
    /* a HUD read-out: a cyan edge left, a violet edge right, a soft glow */
    text-shadow: -0.035em 0.012em 0 rgba(74, 240, 255, 0.85), 0.035em -0.012em 0 rgba(160, 107, 255, 0.85),
      0 0 34px rgba(74, 240, 255, 0.35);
  }
  .hero-title .face.is-on { opacity: 1; }
  @media (prefers-reduced-motion: reduce) {
    .hero-title .face-ai.is-on { opacity: 0; }
    .hero-title .face-si { opacity: 1; }
  }

  /* the signal packets on their wire */
  .hero-title .dots { position: relative; display: inline-flex; align-items: center; gap: 0.12em; margin-left: 0.24em; padding: 0 0.04em; }
  .hero-title .hrow2 .dots { margin-left: 0; margin-right: 0.24em; }
  .hero-title .dots::before {                      /* the wire: a faint line the packets ride on */
    content: ""; position: absolute; left: -0.12em; right: -0.12em; top: 50%; height: 0.02em; margin-top: -0.01em;
    background: linear-gradient(90deg, transparent, rgba(74, 240, 255, 0.5) 12%, rgba(160, 107, 255, 0.5) 88%, transparent);
    opacity: 0; animation: wire-in .8s ease-out .6s both;
  }
  .hero-title .dots i {
    position: relative; display: block; flex: none;
    width: 0.13em; height: 0.13em; border-radius: 50%;
    background: var(--cyan); box-shadow: 0 0 0.22em rgba(74, 240, 255, 0.9);
    animation: packet-in .6s cubic-bezier(.2, .9, .3, 1.2) both;
    transition: width .3s ease, height .3s ease, margin .3s ease, border-radius .3s ease, background-color .3s ease;
  }
  /* with scripts on (assets/js-on.js sets .js in the <head>), the packets wait unseen until hero.js has set their
     landing delays (.landing) - before, they drew at once and some re-landed (owner 2026-10-26: "after a clear it starts
     with some of the bottom line drawn") */
  .js .hero-title:not(.landing) .dots i { animation: none; opacity: 0; }
  .hero-title .dots i:nth-child(3n) { background: #b9a3ff; box-shadow: 0 0 0.22em rgba(160, 107, 255, 0.9); }
  .hero-title.settled .dots i { animation: signal 2.6s ease-in-out infinite; }
  .hero-title:hover .dots i { animation-duration: .6s; }
  @media (max-width: 560px) {
    .hero-title .dots i:nth-child(n+8) { display: none; }
  }

  /* THE WALKING EYE (owner 2026-10-24 "make the ones that walk on the dots be 50% smaller"; 2026-10-25 "make the eyes
     on the dots 50% bigger": 0.21em -> 0.315em; then "make all the eyes that travel along the dots to be 33% larger.
     Leave the last one alone": 0.42em while it walks (then "larger" again: 0.525em), 0.315em on the last packet (.is-last, where it waits while the
     word types). 2026-10-27 "make the eye that walks over the dots the same size as the one on the last dot": the
     walking eye is now 0.315em too - one size, pupil, glance and lashes alike, on every packet. assets/hero.js moves .is-eye along every visible packet; the eye grows into the gaps with negative
     margins, so the row never shifts (it overlaps the next packets' edges while it walks). */
  .hero-title .dots i::before {                     /* the pupil, only on the eye */
    content: ""; position: absolute; left: 50%; top: 50%; width: 0.175em; height: 0.175em; margin: -0.0875em 0 0 -0.0875em;
    border-radius: 50%; background: #04111a; opacity: 0; transition: opacity .15s ease .1s;
  }
  .hero-title .dots i.is-eye {
    /* full size AT ONCE: the eye moves on every ~80 ms, so the packets' .3s grow never finished and the walking eye
       stayed packet-sized (MEASURED 2026-10-25 in WebKit: 0.13-0.19em, owner "need to be 50% larger"). The packet
       it leaves still shrinks back over .3s (its own transition). */
    transition: none;
    width: 0.315em; height: 0.1875em; margin: 0 -0.0925em; border-radius: 0.315em / 0.1875em; z-index: 2;
    background: #e9fdff; box-shadow: 0 0 0.3em rgba(74, 240, 255, 0.9), inset 0 0 0 0.018em var(--cyan);
    animation: none;
  }
  .hero-title .dots i.is-eye::before { width: 0.105em; height: 0.105em; margin: -0.0525em 0 0 -0.0525em; }
  @keyframes eye-look-last { 0%, 20% { transform: translateX(0); } 40%, 55% { transform: translateX(-0.075em); }
    70%, 85% { transform: translateX(0.075em); } 100% { transform: translateX(0); } }
  .hero-title .dots i.is-eye::before { opacity: 1; animation: eye-look-last 1.2s ease-in-out infinite; }
  /* EYELASHES on every eye while the headline has .lashed (assets/hero.js copies it from the LANai eye, so
     SPC_EYE_LASHES in includes/apps.php is the ONE switch - owner "All lashes") */
  .hero-title.lashed .dots i.is-eye::after, .hero-title.lashed .i-eye::before {
    content: ""; position: absolute; left: 50%; background:
      linear-gradient(118deg, transparent 44%, #c9fbff 44% 60%, transparent 60%) left center / 34% 100% no-repeat,
      linear-gradient(90deg, transparent 40%, #c9fbff 40% 60%, transparent 60%) center center / 34% 100% no-repeat,
      linear-gradient(62deg, transparent 40%, #c9fbff 40% 56%, transparent 56%) right center / 34% 100% no-repeat;
    filter: drop-shadow(0 0 0.04em var(--cyan));
  }
  .hero-title.lashed .dots i.is-eye::after { top: -0.075em; width: 0.27em; height: 0.0825em; margin-left: -0.135em; }
  .hero-title.lashed .i-eye::before { top: -0.1em; width: 0.36em; height: 0.11em; margin-left: -0.18em; }

  /* "engineered!": hidden until the walk reaches the end of line 2 (.pre, set by the script), then it pops up */
  .hero-title .eng {
    /* room below for the g's descender: the gradient paints only inside this box (Windows cross-test 2026-10-24) */
    padding-bottom: 0.16em;
    margin-bottom: -0.16em;
    background: linear-gradient(100deg, var(--cyan) 0%, #b6f6ff 24%, #ffffff 33%, #c9b6ff 44%, var(--violet) 56%, var(--violet) 100%);
    background-size: 180% 100%;
    background-position: 0% 0;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
  /* it TYPES in, one letter every 0.25 s from the e; once all are there and the eye has perched on the i, it FLASHES
     and disappears, and the next lap types it again (owner 2026-10-24). No filter and no transform on the word: those
     made the gradient text render soft ("why is engineered blurred?"). hero.js sets .typing (letters hidden until
     .on) and .flash; without the script, or under reduced motion, the word simply shows.
     THE EYE STAYS while the word flashes (owner 2026-10-27 "make it so the eyeball stays visible while engineered! is
     flashing"): the flash blinks the LETTERS (and the drawn stem), never .eng itself - an opacity on .eng would take
     its child, the perched eye, with it. visibility, as the typing uses, so the gradient clip follows the letters. */
  .hero-title.typing .eng .ltr { visibility: hidden; }
  .hero-title.typing .eng .ltr.on { visibility: visible; }
  .hero-title.flash .eng .ltr:not(.i-dot), .hero-title.flash .eng .i-stem, .hero-title.flash:not(.stemmed) .eng .i-dot {
    animation: eng-flash .9s steps(1, end) both; }
  @keyframes eng-flash { 0% { visibility: visible; } 16% { visibility: hidden; } 33% { visibility: visible; }
    50% { visibility: hidden; } 66% { visibility: visible; } 83%, 100% { visibility: hidden; } }

  /* the i of "engineered!": while the eye perches above it, the i is hidden and a drawn STEM stands in its place - the
     i without its dot (owner 2026-10-24: "leave it hiding and draw a line (rect) on top of it for the lower part of
     the i"; the dotless glyph looked odd). hero.js measures the real i's stem (canvas) and sets the stem's box and its
     colour from the word's gradient at that spot. */
  .hero-title .i-host { position: relative; }
  .hero-title .i-stem { position: absolute; display: none; border-radius: 0.02em; }
  /* NEVER a dot on the i (owner 2026-10-24: "do not have a dot on top of the letter i"): once hero.js has measured the
     stem it sets .stemmed - the real i is then always invisible (it only keeps its width) and the stem is the letter,
     typed in with the others (shown once the i is .on) and flashing out with them. Without the script: the plain i. */
  .hero-title.stemmed .eng .i-dot.ltr, .hero-title.stemmed.typing .eng .i-dot.ltr.on { visibility: hidden; }
  .hero-title.stemmed .i-stem { display: block; }
  .hero-title.stemmed.typing .i-dot:not(.on) ~ .i-stem { display: none; }
  .hero-title .i-eye {
    /* top 0.165em -> 0.105em (owner 2026-10-25 "have it land a little higher ... more space under it before the bottom
       of the i"): the gap over the stem grows from ~0.006em to ~0.066em */
    position: absolute; left: 50%; top: 0.105em; width: 0.42em; height: 0.25em; margin-left: -0.21em;
    border-radius: 0.42em / 0.25em; background: #e9fdff; box-shadow: 0 0 0.35em rgba(74, 240, 255, 0.9), inset 0 0 0 0.02em var(--cyan);
    opacity: 0; transform: translateY(-0.45em) scale(.3); transition: opacity .3s ease, transform .45s cubic-bezier(.2, 1.4, .4, 1);
  }
  .hero-title .i-eye::after {
    content: ""; position: absolute; left: 50%; top: 50%; width: 0.14em; height: 0.14em; margin: -0.07em 0 0 -0.07em;
    border-radius: 50%; background: #04111a; box-shadow: 0 0 0 0.03em var(--violet); animation: eye-look 3s ease-in-out infinite;
  }
  .hero-title .i-eye.on { opacity: 1; transform: none; animation: eye-blink 3s infinite; }

  @keyframes packet-in {
    0%   { opacity: 0; transform: translate(-0.6em, -0.5em) scale(.4); }
    70%  { opacity: 1; transform: translate(0.03em, 0.02em) scale(1.3); }
    100% { opacity: 1; transform: none; }
  }
  @keyframes wire-in { from { opacity: 0; transform: scaleX(.2); } to { opacity: 1; transform: none; } }
  @keyframes signal {
    0%, 30%, 100% { opacity: .6; transform: scale(1); }
    12%           { opacity: 1;  transform: scale(1.4); }
  }

  .vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  /* the full width of the page (owner 2026-10-25 "Reflow the text ... It looks jammed to the left": 64ch left a third
     of the 960 px page empty) */
  .hero .tag { max-width: none; font-size: clamp(15px, 1.25vw, 18px); line-height: 1.6; text-wrap: pretty; }

  /* ---- the board ------------------------------------------------------------------------------------------- */
  .board { margin: 34px 0 0; animation: rise .6s ease .15s both; }
  .board-bar {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 0 4px 10px;
    border-bottom: 1px solid var(--line);
  }
  .board h2, .how h2 {
    margin: 0;
    font-size: 22px;
    font-weight: 750;
    letter-spacing: -0.01em;
    color: #fff;
  }
  /* its own page since 2026-10-29: the board's title is the page's h1 */
  .page .board { margin-top: 18px; }
  .board h1 { margin: 0; font-size: 26px; font-weight: 750; letter-spacing: -0.01em; color: #fff; }
  .board-legend { margin: 0; font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap; }
  .board-legend .lamp { margin-left: 6px; }

  .board-group { margin-top: 18px; }
  .board-head {
    margin: 0 0 8px 4px;
    font-size: 13px;
    font-weight: 600;
    color: var(--muted);
    letter-spacing: 0.01em;
  }
  #group-platform .board-head {
    font-size: 22px;
    font-weight: 750;
    letter-spacing: -0.01em;
    color: #fff;
  }
  #group-platform .release { border-style: dashed; }

  .release {
    background: var(--row);
    border: 1px solid var(--line);
    border-radius: 12px;
    margin: 0 0 8px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: border-color .18s, background .18s;
  }
  .release[open] { background: var(--rowhi); border-color: rgba(74, 240, 255, 0.38); }
  .release summary, .release.preview .summary {
    list-style: none;
    cursor: pointer;
    display: grid;
    grid-template-columns: 14px minmax(160px, 15rem) 1fr auto;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    border-radius: 12px;
  }
  .release summary::-webkit-details-marker { display: none; }
  /* a visitor's locked preview row: it does not open - no pointer, no open/close hint */
  .release.preview .summary { cursor: default; }
  .release.preview .rstatus::after { content: none; }
  .release.preview + .locked, .board-group + .locked { margin-top: 16px; }
  .locked.locked-top { margin: 18px 0 4px; }   /* above the preview for a visitor (owner 2026-10-29) */
  .release summary:hover .rname { color: var(--cyan); }
  .release summary:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
  .rname { font-size: 16.5px; font-weight: 700; color: #fff; transition: color .15s; }
  /* a brand name's styled part (Lanai: the "ai", owner 2026-10-24 "go with A") - on the board, in the theatre's reel
     and marquee */
  .ai { color: var(--cyan); text-shadow: 0 0 10px rgba(74, 240, 255, 0.55); }
  /* the Lanai mark's eye (the last i's dot): drawn by the shared brand piece, assets/lanai-brand/lanai-mark.css (owner
     2026-10-27 "A" - one drawing everywhere); only the headline's own eyes are drawn in this file */
  @keyframes eye-look { 0%, 18% { transform: translateX(0); } 28%, 42% { transform: translateX(-0.12em); }
    52%, 66% { transform: translateX(0.12em); } 76%, 100% { transform: translateX(0); } }
  @keyframes eye-blink { 0%, 88%, 94%, 100% { transform: scaleY(1); } 91% { transform: scaleY(0.1); } }
  @media (prefers-reduced-motion: reduce) { .i-eye::after { animation: none; } }
  .rdomain { margin-left: 4px; font: 600 11px/1 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; letter-spacing: .06em;
    color: var(--muted); }
  .rtag { font-size: 14px; color: var(--muted); }
  .rstatus {
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: 12px;
    color: var(--text);
    opacity: 0.8;
    white-space: nowrap;
  }
  .rstatus::after {             /* the open/close hint, turns when the row opens */
    content: "";
    display: inline-block;
    width: 7px; height: 7px;
    margin-left: 12px;
    border-right: 1.5px solid var(--muted);
    border-bottom: 1.5px solid var(--muted);
    transform: translateY(-2px) rotate(45deg);
    transition: transform .2s ease;
  }
  .release[open] .rstatus::after { transform: translateY(1px) rotate(225deg); }

  .lamp {
    display: inline-block;
    width: 9px; height: 9px;
    border-radius: 50%;
    flex: 0 0 auto;
  }
  .lamp-live  { background: var(--live);  box-shadow: 0 0 10px var(--live); }
  .lamp-beta  { background: var(--beta);  box-shadow: 0 0 10px rgba(255, 200, 87, 0.7); }
  .lamp-inuse { background: var(--inuse); box-shadow: 0 0 10px var(--inuse); }
  .board .release .lamp-live { animation: pulse 2.4s ease-in-out infinite; }

  .rbody {
    padding: 0 18px 18px calc(18px + 14px + 14px);   /* lines up under the name */
    animation: open .22s ease both;
  }
  @keyframes open { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
  .rbody p { margin: 0 0 12px; max-width: 68ch; font-size: 14.5px; line-height: 1.6; color: var(--text); }

  .chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; padding: 0; list-style: none; }
  .chips li {
    font-size: 12px;
    color: var(--cyan);
    background: rgba(74, 240, 255, 0.07);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 3px 8px;
  }

  .actions { display: flex; gap: 10px; flex-wrap: wrap; }
  .btn {
    display: inline-block;
    padding: 10px 16px;
    border-radius: 10px;
    font-size: 13.5px;
    font-weight: 650;
    text-decoration: none;
    white-space: nowrap;
    transition: transform .12s, filter .18s, border-color .18s, color .18s;
  }
  .btn.primary { color: #04111a; background: linear-gradient(100deg, var(--cyan), var(--violet)); }
  .btn.primary:hover { transform: translateY(-1px); filter: brightness(1.07); }
  .btn.ghost { color: var(--text); background: rgba(4, 7, 16, 0.65); border: 1px solid var(--line); }
  .btn.ghost:hover { border-color: var(--cyan); color: var(--cyan); }
  .btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

  /* ---- How it's built ---------------------------------------------------------------------------------------- */
  .how { margin: 48px 0 0; padding-top: 16px; border-top: 1px solid var(--line); }
  /* the How pages' strip: Built · Tested · Runs (includes/nav.php spc_how_strip, owner 2026-10-28) */
  /* the three How pages' title graphic (owner 2026-10-29): Built -> Tested -> Runs on one wire, the current step lit
     and the wire lit up to it (.at1/.at2/.at3); the page's h1 is visually hidden behind it */
  /* one opening for all three pages (owner 2026-10-29 "make their formatting look more standardized ... a little
     space between the menu label line and the first real page data"; then "move the text to under the graphic ...
     leave some space above the graphics"): the step graphic, a faint rule, 36 px of air, the page's infographic, then
     its lead paragraph 30 px under it */
  .how-steps { margin: 22px 0 0; padding-bottom: 26px; border-bottom: 1px solid var(--line); }
  .page .how > h1.vh + figure { margin-top: 36px; }
  .page .how figure + .how-lead { margin: 30px 0 0; }
  /* ... and 30 px under the lead on every page, whatever comes next (owner 2026-10-29 "yes make it even": it was
     26/30/34 px - each next element kept its own top margin) */
  .page .how .how-lead + * { margin-top: 30px; }
  .hs-kicker { margin: 0 0 16px; text-align: center; font: 700 15px/1.3 var(--mono, ui-monospace, monospace);
    letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }   /* larger, centred (owner 2026-10-29) */
  .hs-kicker .lanai-mark { text-transform: none; letter-spacing: .04em; color: #fff; }
  .hs-kicker span { text-transform: none; letter-spacing: .06em; color: #c9fbff; }   /* "Delivering Solutions!" as the owner wrote it */
  .how-steps ol { position: relative; display: grid; grid-template-columns: repeat(5, 1fr); margin: 0; padding: 0;
    list-style: none; }
  /* the wire: centre of step 1 to centre of step 5 (Overview, Controlling, Building, Testing, Operating - owner
     2026-10-29), and its lit part up to the current step */
  .how-steps ol::before, .how-steps ol::after { content: ""; position: absolute; top: 21px; left: 10%; height: 2px;
    border-radius: 2px; }
  .how-steps ol::before { right: 10%; background: var(--line); }
  .how-steps ol::after { width: 0; background: linear-gradient(90deg, var(--cyan), var(--violet));
    box-shadow: 0 0 10px rgba(74, 240, 255, 0.6); animation: hs-wire .9s ease .2s both; }
  .how-steps.at2 ol::after { --hs-w: 20%; }
  .how-steps.at3 ol::after { --hs-w: 40%; }
  .how-steps.at4 ol::after { --hs-w: 60%; }
  .how-steps.at5 ol::after { --hs-w: 80%; }
  @keyframes hs-wire { to { width: var(--hs-w, 0); } }
  .hs a { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 0 6px; text-align: center; text-decoration: none; }
  .hs-dot { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; margin-bottom: 6px;
    font-size: 17px; font-weight: 800; line-height: 1; color: var(--muted); background: #070b18; border: 2px solid var(--line);
    transition: border-color .2s, color .2s; }
  .hs-name { font-size: 15px; font-weight: 600; color: var(--muted); white-space: nowrap; }
  .hs-name b { font-weight: 800; }
  .hs-sub { font-size: 12px; color: var(--muted); opacity: .75; }
  .hs a:hover .hs-dot, .hs a:focus-visible .hs-dot { border-color: var(--cyan); color: #fff; }
  .hs a:hover .hs-name, .hs a:focus-visible .hs-name { color: #fff; }
  .hs.on .hs-dot { color: #04131a; border-color: transparent; background: linear-gradient(135deg, var(--cyan), var(--violet));
    box-shadow: 0 0 0 5px rgba(74, 240, 255, 0.12), 0 0 22px rgba(74, 240, 255, 0.55); animation: hs-pulse 2.6s ease-in-out infinite; }
  .hs.on .hs-name { color: #fff; font-size: 18px; }
  .hs.on .hs-name b { background: linear-gradient(100deg, #fff, var(--cyan)); -webkit-background-clip: text;
    background-clip: text; color: transparent; }
  .hs.on .hs-sub { color: #c9fbff; opacity: 1; }
  @keyframes hs-pulse {
    0%, 100% { box-shadow: 0 0 0 5px rgba(74, 240, 255, 0.12), 0 0 22px rgba(74, 240, 255, 0.55); }
    50%      { box-shadow: 0 0 0 9px rgba(74, 240, 255, 0.05), 0 0 30px rgba(160, 107, 255, 0.6); }
  }
  @media (max-width: 560px) {
    .hs-sub { display: none; }
    .hs-name, .hs.on .hs-name { font-size: 11px; white-space: normal; }
    .hs.on .hs-name { font-size: 12px; }
    .hs-kicker { font-size: 12.5px; margin-bottom: 14px; }
    .hs a { padding: 0 2px; }
    .hs-dot { width: 32px; height: 32px; font-size: 14px; }
    .how-steps ol::before, .how-steps ol::after { top: 15px; }
    .how-steps { padding-bottom: 20px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .how-steps ol::after { animation: none; width: var(--hs-w, 0); }
    .hs.on .hs-dot { animation: none; }
  }

  /* the foot of each Lanai page (owner 2026-10-29 "just have Lanai: (and one word links to the others)") */
  .how .lanai-foot { text-align: center; font-size: 15px; color: var(--muted); }
  .lanai-foot b { margin-right: 6px; color: #fff; font-weight: 800; }
  .lanai-foot a { font-weight: 600; text-decoration: none; }
  .lanai-foot a:hover, .lanai-foot a:focus-visible { text-decoration: underline; }
  .lanai-foot .sep { margin: 0 6px; opacity: .6; }

  /* ---- Overview (owner 2026-10-29: the first tab): the four parts on one wire, a packet crossing it in 8 s and
     lighting each card in turn, then round again; a phone gets its .mflow instead */
  .ovw { position: relative; margin: 0; padding: 30px 28px 26px; border-radius: 22px; text-align: center;
    border: 1px solid rgba(120, 220, 255, 0.18);
    background: linear-gradient(160deg, rgba(74, 240, 255, 0.06), rgba(160, 107, 255, 0.05) 60%, rgba(4, 7, 18, 0.55)); }
  .how .ovw-kicker { margin: 0 0 6px; font: 700 12px/1.3 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    letter-spacing: .16em; text-transform: uppercase; color: var(--cyan); }
  .ovw-kicker .lanai-mark { text-transform: none; letter-spacing: .04em; color: #fff; }
  .page .how h2.ovw-title { margin: 0 0 26px; font-size: clamp(24px, 3.2vw, 34px); font-weight: 800; letter-spacing: -0.015em;
    color: #fff; }
  .ovw-row { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin: 0; padding: 0;
    list-style: none; text-align: left; }
  .ovw-row::before { content: ""; position: absolute; left: 12.5%; right: 12.5%; top: 22px; height: 2px; border-radius: 2px;
    background: var(--line); }
  .ov a { position: relative; display: flex; flex-direction: column; height: 100%; padding: 0 16px 18px; border-radius: 16px;
    text-decoration: none; border: 1px solid transparent; animation: ov-card 8s ease-in-out infinite both; }
  .ov a:hover, .ov a:focus-visible { border-color: var(--cyan); }
  .ov-dot { align-self: center; position: relative; z-index: 1; display: grid; place-items: center; width: 44px; height: 44px;
    margin-bottom: 14px; border-radius: 50%; font-size: 17px; font-weight: 800; color: var(--muted); background: #070b18;
    border: 2px solid var(--line); animation: mf-light 8s ease-in-out infinite both; }
  .how .ov b { display: block; margin-bottom: 6px; text-align: center; font-size: 18px; font-weight: 800; color: #fff; }
  .how .ov a > span:not(.ov-dot) { display: block; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
  .ov.o2 a, .ov.o2 .ov-dot { animation-delay: 2s; }
  .ov.o3 a, .ov.o3 .ov-dot { animation-delay: 4s; }
  .ov.o4 a, .ov.o4 .ov-dot { animation-delay: 6s; }
  @keyframes ov-card {
    0%, 62%, 100% { background: transparent; }
    6%, 48%       { background: rgba(74, 240, 255, 0.06); }
  }
  /* the packet: the wire's own dot, card 1 to card 4 in 6 s, then it fades and starts again */
  .ovw-row::after { content: ""; position: absolute; z-index: 2; top: 17px; left: 12.5%; width: 12px; height: 12px;
    margin-left: -6px; border-radius: 50%; background: #fff; box-shadow: 0 0 10px var(--cyan), 0 0 22px rgba(74, 240, 255, 0.8);
    pointer-events: none; animation: ov-run 8s linear infinite both; }
  @keyframes ov-run {
    0%        { left: 12.5%; opacity: 0; }
    3%        { opacity: 1; }
    75%       { left: 87.5%; opacity: 1; }
    85%, 100% { left: 87.5%; opacity: 0; }
  }
  .how .ovw-loop { margin: 20px 0 0; }
  .ovw-loop span { display: inline-block; padding: 5px 14px; border-radius: 999px; border: 1px dashed var(--line);
    font: 600 11.5px/1.2 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; letter-spacing: .08em; color: var(--muted); }
  @media (prefers-reduced-motion: reduce) {
    .ov a, .ovw-row::after { animation: none; }
    .ovw-row::after { display: none; }
    .ov-dot { animation: none; color: #04131a; background: linear-gradient(135deg, var(--cyan), var(--violet)); border-color: transparent; }
  }

  /* ---- the Lanai System pages on a phone (owner 2026-10-29: "all of this looks too much and too busy on a mobile
     device ... clear mobile versions where each one had an animation flowing and describing that portion"): the big
     infographic and the detail lists (.m-hide) step aside for one flow (includes/nav.php spc_mobile_flow) - five
     stations on a wire, a packet running down it lighting each in turn, then the verdict. A 10 s lap: the packet
     reaches station n at (n-1) x 2 s; each station's light uses the same keyframes, started n-1 laps-of-2-s later. */
  .mflow { display: none; }
  @media (max-width: 640px) {
    .page .how .m-hide { display: none; }   /* beats .how-cols' / a figure's own display */
    .mflow { display: block; margin: 28px 0 0; padding: 22px 18px 20px; border-radius: 18px; text-align: left;
      border: 1px solid rgba(120, 220, 255, 0.22);
      background: linear-gradient(160deg, rgba(74, 240, 255, 0.07), rgba(160, 107, 255, 0.06) 60%, rgba(4, 7, 18, 0.6));
      box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35); }
    .page .how .mflow + .how-lead { margin-top: 26px; }
  }
  .how .mf-kicker { margin: 0 0 6px; text-align: center; font: 700 11.5px/1.3 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    letter-spacing: .16em; text-transform: uppercase; color: var(--cyan); }
  .mf-kicker .lanai-mark { text-transform: none; letter-spacing: .04em; color: #fff; }
  .page .how h2.mf-title { margin: 0 0 18px; text-align: center; font-size: 21px; font-weight: 800; line-height: 1.25;
    letter-spacing: -0.01em; color: #fff; }
  .mf-track { position: relative; }
  .mf-steps { position: relative; display: grid; grid-auto-rows: 1fr; gap: 0; margin: 0; padding: 0; list-style: none; }
  /* the wire through the five dots' centres (the dots are 34 px, so it runs 17 px in from the left) */
  .mf-track::before { content: ""; position: absolute; left: 16px; top: 10%; bottom: 10%; width: 2px; border-radius: 2px;
    background: var(--line); }
  .mf { position: relative; display: grid; grid-template-columns: 34px 1fr; column-gap: 14px; align-content: center;
    min-height: 64px; padding: 6px 0; }
  .mf-dot { grid-row: 1 / 3; align-self: center; position: relative; z-index: 1; display: grid; place-items: center;
    width: 34px; height: 34px; border-radius: 50%; font-size: 14px; font-weight: 800; color: var(--muted);
    background: #070b18; border: 2px solid var(--line); animation: mf-light 10s ease-in-out infinite both; }
  .how .mf b { display: block; font-size: 15.5px; font-weight: 750; color: #c9d4ee; animation: mf-name 10s ease-in-out infinite both; }
  .how .mf span:not(.mf-dot) { display: block; font-size: 13.5px; line-height: 1.45; color: var(--muted); }
  .mf.s2 .mf-dot, .mf.s2 b { animation-delay: 2s; }
  .mf.s3 .mf-dot, .mf.s3 b { animation-delay: 4s; }
  .mf.s4 .mf-dot, .mf.s4 b { animation-delay: 6s; }
  .mf.s5 .mf-dot, .mf.s5 b { animation-delay: 8s; }
  @keyframes mf-light {
    0%, 100% { color: var(--muted); background: #070b18; border-color: var(--line); box-shadow: none; transform: scale(1); }
    4%       { color: #04131a; background: linear-gradient(135deg, var(--cyan), var(--violet)); border-color: transparent;
               box-shadow: 0 0 0 6px rgba(74, 240, 255, 0.14), 0 0 22px rgba(74, 240, 255, 0.6); transform: scale(1.12); }
    12%, 50% { color: #04131a; background: linear-gradient(135deg, var(--cyan), var(--violet)); border-color: transparent;
               box-shadow: 0 0 0 3px rgba(74, 240, 255, 0.10), 0 0 12px rgba(74, 240, 255, 0.35); transform: scale(1); }
    62%      { color: var(--muted); background: #070b18; border-color: var(--line); box-shadow: none; transform: scale(1); }
  }
  @keyframes mf-name {
    0%, 62%, 100% { color: #c9d4ee; }
    4%, 50%       { color: #fff; }
  }
  /* the packet: down the wire from station 1 to 5 in 8 s, then it fades while the verdict shows */
  .mf-pkt { position: absolute; z-index: 2; left: 11px; top: 10%; width: 12px; height: 12px; margin-top: -6px; border-radius: 50%;
    background: #fff; box-shadow: 0 0 10px var(--cyan), 0 0 22px rgba(74, 240, 255, 0.8);
    animation: mf-run 10s linear infinite both; }
  @keyframes mf-run {
    0%   { top: 10%; opacity: 0; }
    3%   { opacity: 1; }
    80%  { top: 90%; opacity: 1; }
    88%, 100% { top: 90%; opacity: 0; }
  }
  .how .mf-verdict { margin: 14px 0 0; text-align: center; }
  .mf-verdict em { display: inline-block; padding: 6px 14px; border-radius: 999px; font-style: normal;
    font: 700 12.5px/1.2 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; letter-spacing: .08em;
    color: #04131a; background: linear-gradient(100deg, var(--cyan), var(--violet));
    animation: mf-verdict 10s ease-in-out infinite both; }
  @keyframes mf-verdict {
    0%, 78%  { opacity: .25; transform: scale(.96); box-shadow: none; }
    84%, 96% { opacity: 1; transform: scale(1); box-shadow: 0 0 22px rgba(74, 240, 255, 0.55); }
    100%     { opacity: .25; transform: scale(.96); box-shadow: none; }
  }
  @media (prefers-reduced-motion: reduce) {   /* still: every station lit, the verdict shown, no packet */
    .mf-dot { animation: none; color: #04131a; background: linear-gradient(135deg, var(--cyan), var(--violet)); border-color: transparent; }
    .how .mf b { animation: none; color: #fff; }
    .mf-pkt { display: none; }
    .mf-verdict em { animation: none; }
  }
  /* the Lanai pieces as cards (owner 2026-10-29: moved off the board onto the Lanai pages - "embellish, clean,
     nice-ify"): a glass card with a lit edge, the brand name large, the tagline in ice, then what it does */
  .pieces-wrap { margin: 34px 0 30px; text-align: center; }
  .how .pieces-kicker { margin: 0 0 6px; font: 700 12px/1.3 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    letter-spacing: .16em; text-transform: uppercase; color: var(--cyan); }
  .pieces-kicker .lanai-mark { text-transform: none; letter-spacing: .04em; color: #fff; }
  .page .how h2.pieces-head { margin: 0 0 18px; font-size: clamp(22px, 3vw, 28px); font-weight: 800;
    letter-spacing: -0.01em; color: #fff; }
  .pieces { display: grid; gap: 18px; text-align: left; }
  .pieces-1 { max-width: 760px; margin: 0 auto; }
  .pieces-2 { grid-template-columns: repeat(2, 1fr); }
  .piece { position: relative; display: flex; flex-direction: column; padding: 22px 24px 20px; border-radius: 18px;
    border: 1px solid rgba(120, 220, 255, 0.22); overflow: hidden;
    background: linear-gradient(160deg, rgba(74, 240, 255, 0.07), rgba(160, 107, 255, 0.06) 60%, rgba(4, 7, 18, 0.6));
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.06); }
  .piece::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px;
    background: linear-gradient(90deg, transparent, var(--cyan) 30%, var(--violet) 70%, transparent); opacity: .8; }
  .how .piece-status { display: inline-flex; align-items: center; gap: 8px; align-self: flex-start; margin: 0 0 12px;
    padding: 4px 11px 4px 9px; border-radius: 999px; border: 1px solid var(--line); background: rgba(255, 255, 255, 0.04);
    font: 600 11px/1 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; letter-spacing: .1em; text-transform: uppercase;
    color: #c9d4ee; }
  .piece-status .lamp { margin: 0; }
  .page .how .piece-name { margin: 0 0 4px; font-size: 26px; font-weight: 800; letter-spacing: -0.01em; color: #fff; }
  .piece-name .rdomain { vertical-align: middle; }
  .how .piece-tag { margin: 0 0 12px; font-size: 15px; font-weight: 600; color: #c9fbff; }
  .how .piece-desc { margin: 0 0 14px; font-size: 14px; line-height: 1.6; color: var(--muted); }
  .piece .chips { margin-bottom: 16px; }
  .piece .actions { margin-top: auto; }
  .how .piece-lock { margin: auto 0 0; font-size: 13px; color: var(--muted); }
  .piece-lock a { color: var(--cyan); }
  @media (max-width: 760px) { .pieces-2 { grid-template-columns: 1fr; } }
  .how-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; margin-top: 16px; }
  .how h3 { margin: 0 0 6px; font-size: 15.5px; font-weight: 700; color: #fff; }
  .how p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--muted); }
  /* "How the apps are tested" (owner 2026-10-27): a full-width part under the three columns */
  .how-tested { margin-top: 28px; }
  .how-tested p { margin-bottom: 10px; }
  .how-tested ul { margin: 0; padding: 0 0 0 18px; display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 28px; }
  .how-tested li { font-size: 14px; line-height: 1.55; color: var(--muted); }
  .how-tested li b { color: #fff; font-weight: 600; }
  /* How it's built and How it's tested as pages of their own (owner 2026-10-27): no rule above the first section, the
     page title as the h1, the ATS path as a numbered list */
  .page .how { margin-top: 12px; padding-top: 0; border-top: 0; }
  .page .how h1 { margin: 8px 0 14px; }
  .page .how h2 { margin: 30px 0 12px; font-size: 19px; }
  .how .how-lead { max-width: 74ch; font-size: 15.5px; color: var(--text); }
  .how .how-next { margin-top: 30px; }
  .how-next a { color: var(--cyan); }
  .steps { margin: 0; padding: 0 0 0 22px; display: grid; gap: 10px; max-width: 86ch; }
  .steps li { font-size: 14px; line-height: 1.6; color: var(--muted); }
  .steps li b { color: #fff; font-weight: 600; }

  /* ---- Contact: the form keeps its narrow card -------------------------------------------------------------- */
  #contact { max-width: 640px; margin: 52px auto 0; scroll-margin-top: 24px; }
  #releases, #how { scroll-margin-top: 24px; }
  .contact-title { margin: 0 0 16px; font-size: 19px; font-weight: 700; color: #fff; text-align: center; }   /* owner 2026-10-25: centred */

  @media (max-width: 760px) {
    /* line 2 (25 packets + "engineered!") is ~11.8em wide: the type follows the width so it always fits (566 px
       overflowed at a fixed 60 px - MEASURED 2026-10-24) */
    .hero-title { font-size: clamp(30px, calc((100vw - 56px) / 12.1), 60px); }
    .how-cols { grid-template-columns: 1fr; gap: 18px; }
    .how-tested ul { grid-template-columns: 1fr; }
    .release summary, .release.preview .summary { grid-template-columns: 12px 1fr auto; gap: 4px 12px; }
    .rtag { grid-column: 2 / 4; grid-row: 2; font-size: 13.5px; }
    .rbody { padding: 0 16px 16px; }
  }
  @media (max-width: 560px) {
    /* 7 packets a row (above): line 2 (7 packets + "engineered!") is now the wider one, ~7.4em */
    .hero-title { font-size: clamp(30px, calc((100vw - 44px) / 7.6), 52px); }
    .nav { gap: 14px; }
    .top { flex-wrap: wrap; row-gap: 12px; }
    .board-legend { display: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .board, .rbody, .board .release .lamp-live { animation: none; }
    .release, .rstatus::after, .btn { transition: none; }
  }
