/* undercurrent.observer, layout v2 (15 Oct 2026)
   Light only, on cream. Tokens and type scale follow the design board (C:\website\design-board).
   Layout: a narrow fixed left nav, then a single content column with hairline borders. */

/* Söhne Buch, licensed (Klim Web licence for undercurrent.observer,
   Buch style ONLY). There is no licensed italic or bold: every weight is
   400, font-synthesis is off (no faux bold or italic), and emphasis elements stay upright. */
@font-face { font-family: "Söhne"; src: url("../fonts/soehne-buch.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }

:root {
  /* Colour (design board) */
  --bg: #f7f3ea;       /* cream ground */
  --card: #fcfaf5;     /* raised surfaces */
  --sand: #efe9dc;     /* quiet fills, textured panel */
  --line: #e2daca;     /* hairlines */
  --line-2: #cdc3af;   /* stronger hairlines, outlined buttons */
  --text: #0f1b2a;
  --muted: #4c5662;
  --dim: #636b73;
  --blue: #0070fe;     /* logo blue: accents, buttons, graphics, large text only */
  --deep: #00318c;     /* deep blue: small blue text (10.4:1 on cream) */
  --pale: #eef4fd;     /* blue tint for additions and chips */
  --pale-line: #99c6ff;

  /* Type (locked 15 Oct, implemented site-wide): Söhne Buch is the ONLY typeface, the logo
     wordmark excepted (it is drawn as SVG, not set in a font). --mono points at Söhne too:
     tickers, times and code-like labels are Söhne Buch with tabular figures (see .tnum below).
     Only Buch (400) exists, so every weight is 400 and font-synthesis is off (no faux bold or
     faux italic). The licensed @font-face is at the top of this file. See README. */
  --sans: "Söhne", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: var(--sans);
  --weight: 400;

  --nav-w: 216px;
  --gutter: 16px;
  --radius: 12px;
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 24px; font-synthesis: none; }
body { margin: 0; background: var(--bg); color: var(--text); font: var(--weight) 16px/1.6 var(--sans); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
h1, h2, h3, p, ul, ol { margin: 0; }
h1, h2, h3, h4, h5, h6, b, strong, th, dt, legend, optgroup { font-weight: var(--weight); }
em, i, cite, var, dfn, address { font-style: normal; } /* no licensed italic */
code, kbd, samp, pre { font-family: var(--mono); font-size: 1em; }
/* Tabular figures wherever times and numbers must line up: the dashboard demo, the How it works
   figures, tables, code-like text and times. Prose keeps proportional figures. */
.tnum, .demo-block, .hw-fig, .hw-index, table, code, kbd, samp, pre, time, .step-n { font-variant-numeric: tabular-nums; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
a { color: inherit; }
button, select, input, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; border-radius: 4px; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.skip { position: absolute; left: 12px; top: -48px; background: var(--text); color: #fff; padding: 8px 12px; border-radius: 6px; z-index: 50; text-decoration: none; }
.skip:focus { top: 12px; }

/* ---------------------------------------------------------------- shell + left nav */
.shell { min-height: 100vh; }
.side { position: sticky; top: 0; z-index: 20; background: var(--bg); border-bottom: 1px solid var(--line); }
.side-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 12px var(--gutter); }
.brand { display: inline-flex; padding: 4px 0; }
.brand img { height: 26px; width: auto; }
.menu-btn { background: none; border: 1px solid var(--line-2); border-radius: 8px; min-height: 36px; padding: 0 14px; font-size: 14px; cursor: pointer; }
.side-nav { display: none; width: 100%; padding: 8px 0 6px; }
.side-nav.open { display: block; }
.side-nav a { display: block; padding: 5.5px 0; text-decoration: none; color: var(--muted); font-size: 15px; }
.side-nav a:hover, .side-nav a[aria-current] { color: var(--text); }
.side-nav a:focus-visible { outline: none; }
.side-nav li { position: relative; padding-left: 26px; }
/* Current section: the logo mark beside the label, revealed left to right as if drawn.
   A soft-edged mask slides across it; un-drawing slides it back. JS sets --dur
   (slow reveal on click, quicker on scroll-spy). */
.nav-mark { position: absolute; left: 0; top: 50%; width: 17px; height: auto; margin-top: -6px; pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, #000 0 50%, transparent 55% 100%); mask-image: linear-gradient(90deg, #000 0 50%, transparent 55% 100%);
  -webkit-mask-size: 220% 100%; mask-size: 220% 100%; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: 100% 0; mask-position: 100% 0;
  transition: -webkit-mask-position var(--dur, .45s) cubic-bezier(.3, .1, .3, 1), mask-position var(--dur, .45s) cubic-bezier(.3, .1, .3, 1); }
.nav-mark.on { -webkit-mask-position: 0 0; mask-position: 0 0; }
/* Hover and keyboard focus: a straight bar (exactly as wide as the label, 4.5 px taller above and
   below, laid over it so nothing moves) sits behind it and wipes in
   from left to right with a hard edge; a copy of the label in white rides on the bar, so the text
   inverts exactly where the bar has reached. site.js drives the edge with a critically damped
   spring (it halves the remaining distance every frame: about 90% in 55 ms, settled by 150 ms),
   and the same spring retracts it right to left. Bar colours keep white text above 4.5:1:
   #006CF5 (4.7:1) for the other sections, deep navy #00318C (12.6:1) for the current section. */
.nl { position: relative; display: inline-block; white-space: nowrap; }
.nl-hl { --bar: #006cf5; position: absolute; left: 0; top: 50%; padding: 4.5px 0; transform: translateY(-50%); color: #fff; pointer-events: none; white-space: nowrap; line-height: 1;
  -webkit-mask-image: linear-gradient(to right, #000 var(--p, 0%), transparent var(--p, 0%)); mask-image: linear-gradient(to right, #000 var(--p, 0%), transparent var(--p, 0%)); }
.nl-hl::before { content: attr(data-t); position: relative; z-index: 1; }
.nl-hl i { position: absolute; inset: 0; background: var(--bar); transition: background-color .1s; }
.side-nav a[aria-current] .nl-hl { --bar: #00318c; }
.side-tag { margin-top: 18px; font-size: 13px; letter-spacing: 0; color: var(--deep); }
.side-tag::before { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; border: 1px solid var(--blue); margin-right: 8px; vertical-align: 1px; }

@media (min-width: 960px) {
  :root { --gutter: 40px; }
  .side { position: fixed; inset: 0 auto 0 0; width: var(--nav-w); border-bottom: 0; background: transparent; }
  .side-inner { flex-direction: column; align-items: flex-start; justify-content: flex-start; flex-wrap: nowrap; gap: 28px; padding: 36px 24px 36px 32px; height: 100%; }
  .menu-btn { display: none; }
  .side-nav { display: flex; flex-direction: column; flex: 1; padding: 0; }
  .side-nav ul { display: grid; gap: 0; }
  .side-nav a { padding: 2px 0; min-height: 24px; }
  .side-tag { margin-top: auto; }
  .main { margin-left: var(--nav-w); }
}

/* ---------------------------------------------------------------- content column */
.main { max-width: calc(1200px + var(--nav-w)); padding: 0 var(--gutter); }
@media (min-width: 960px) { .main { max-width: 1240px; padding: 0 56px 0 24px; } }
.block { padding: 72px 0; border-top: 1px solid var(--line); }
@media (min-width: 960px) { .block { padding: 104px 0; } }

.eyebrow { font-size: 15px; letter-spacing: 0; color: var(--deep); } /* sentence case, as written (user 16 Oct) */
.sec-head { display: grid; gap: 10px; margin-bottom: 36px; }
.sec-head h2 { font-size: clamp(26px, 3.4vw, 34px); letter-spacing: -0.025em; line-height: 1.15; max-width: 26ch; }
.soft { color: var(--dim); }
.sec-head-row { grid-template-columns: 1fr; align-items: end; }
@media (min-width: 760px) { .sec-head-row { grid-template-columns: 1fr auto; gap: 24px; } }

/* buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 20px; border-radius: 8px; font: var(--weight) 15px/1 var(--sans); text-decoration: none; cursor: pointer; white-space: nowrap; border: 1px solid transparent; transition: background-color .15s, border-color .15s; }
.btn-pri { background: var(--blue); color: #fff; }
.btn-pri:hover { background: #005fd9; }
.btn-sec { border-color: var(--line-2); color: var(--text); background: transparent; }
.btn-sec:hover { border-color: var(--text); }
.btn-sm { min-height: 36px; padding: 0 14px; font-size: 14px; }

/* ---------------------------------------------------------------- hero */
.hero { padding: 48px 0 72px; }
@media (min-width: 960px) { .hero { padding: 96px 0 104px; } }
.hero-row { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 24px 48px; margin-bottom: 40px; }
.hero h1 { flex: 1 1 560px; max-width: 30ch; font-size: clamp(30px, 4vw, 48px); line-height: 1.08; letter-spacing: -0.035em; }
/* Hero (15 Oct): the headline in two lines from 760 px (an explicit break after "websites"),
   four below (breaks after "change", "websites" and "say,"), sized to the hero's width so its longest line
   always fits, also while it plays; the particle field (field.js) is a layer behind the whole
   hero and forms the mark beside the headline, or in the space kept under it below 1380 px
   (--hero-slot tells field.js which). */
.hero { position: relative; container-type: inline-size; --hero-slot: beside; }
.hero-row { position: relative; z-index: 1; align-items: center; flex-wrap: nowrap; }
.hero h1.hl { flex: 0 1 auto; max-width: none; font-size: clamp(26px, calc(100cqi / 19.4), 48px); }
.hero-art { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
/* the field reaches --art-below past the hero, behind the demo frame (which paints over it: it comes
   later and is positioned), so a thinner drift of cubes carries on round and out from behind the
   frame, mostly in the free space on its right (user 16 Oct); field.js skips what the frame hides */
.hero { --art-below: 440px; }
.hero-art { bottom: calc(-1 * var(--art-below)); }
/* from 1280 px the demo leaves free space on its right: the drift runs further down beside it (user 16 Oct) */
@media (min-width: 1280px) { .hero { --art-below: 690px; } }
@media (max-width: 759px) { .hero { --art-below: 260px; } }
.hl .nw { white-space: nowrap; }
/* from 960 px the field bleeds into the right margin; from 1380 px the row keeps room for the mark */
@media (min-width: 960px) { .hero-art { right: -56px; } }
@media (min-width: 1380px) { .hero-row { min-height: 168px; } }
@media (min-width: 1800px) { .main > section.hero { max-width: none; } }
@media (max-width: 1379px) { .hero { --hero-slot: below; } .main > section.hero { padding-bottom: 168px; } }
@media (max-width: 759px) { .hero h1.hl { font-size: clamp(20px, calc(100cqi / 11.8), 44px); } .main > section.hero { padding-bottom: 150px; } }
/* without JavaScript there is no field, so no space is kept for it */
.no-js .main > section.hero { padding-bottom: 28px; }
@media (min-width: 960px) { .no-js .main > section.hero { padding-bottom: 40px; } }
.cta { display: flex; flex-wrap: wrap; gap: 10px; }
/* Headline word diffs (site.js "hero"): "edit" is struck through and dims, then "change" is
   revealed beside it in blue; then "companies" becomes "company websites"; then "announce" is
   struck and "say" revealed. Only transform and opacity animate (composited, no layout per
   frame): every word keeps its final width from the start, the strike is a scaleX line, and each
   new word is wiped in by a window that slides right while its text slides the other way by the
   same amount, so the text stays still. The words after it on the same line (.dw-f) start pulled
   left by the new word's width (--s1..--s4, measured by site.js) and slide right as the window
   opens, so the line reads with normal spacing at every moment. The default is the settled state
   (struck, dimmed old words; blue new words): that is what shows with reduced motion or without
   the script; .arm is the "before" state the script plays from. */
.dw { white-space: nowrap; }
.dw-o { position: relative; opacity: .5; transition: opacity .45s ease; }
.dw-o::after { content: ""; position: absolute; left: -.03em; right: -.03em; top: 54%; height: max(2px, .065em); background: currentColor; border-radius: 1px;
  transform: scaleX(1); transform-origin: left center; transition: transform .5s cubic-bezier(.3, .7, .2, 1); }
.dw-n { color: var(--blue); margin-left: .25em; }
/* "companies" -> "company websites" (user 16 Oct): the "ies" starts in the headline's ink like
   "compan", is struck through and turns grey, then squashes away to its left edge (scaleX, it is
   out of flow: position absolute at its own place, so the settled line has no gap); the "y" is
   then wiped in right beside "compan" in the logo blue and turns to ink, so "company" settles as
   one word. "websites" (.dw-add, no old word) grows in after it in the logo's deep blue, darker
   than "change" and "say". Settled (CSS default, reduced motion, no script) = "company websites". */
.dw-y { position: relative; }
.dw-y .dw-o { position: absolute; white-space: nowrap; color: var(--dim); opacity: 0; transform: scaleX(0); transform-origin: left center;
  transition: color .4s ease, transform .45s cubic-bezier(.5, 0, .2, 1) .55s, opacity .2s ease .8s; }
.dw-y .dw-o::after { transition-duration: .4s; }
.dw-y.arm .dw-o { color: var(--text); opacity: 1; transform: none; transition: color .3s ease, transform .3s ease, opacity .2s ease; }
.dw-y .dw-n { margin-left: 0; color: var(--text); transition: color .6s ease 1.9s; }
.dw-y.arm .dw-n { color: var(--blue); transition: none; }
.dw-y .dw-w, .dw-y .dw-t { transition-delay: .9s; transition-duration: .6s; }
.dw-add .dw-n { color: var(--deep); }
/* the clip window reaches a little past each side of the word: with the headline's tight
   letter-spacing a glyph's ink (the tail of a "y", the last "s") runs past its advance */
.dw-w { display: inline-block; vertical-align: bottom; overflow: clip; padding: .12em .08em .22em; margin: -.12em -.08em -.22em; }
.dw-t { display: inline-block; }
.dw-w, .dw-t { transform: none; transition: transform .75s cubic-bezier(.3, .7, .2, 1) .45s; }
.dw.arm .dw-o { opacity: 1; transition-duration: .3s; }
.dw.arm .dw-o::after { transform: scaleX(0); transition-duration: .3s; }
.dw.arm .dw-w { transform: translateX(-101%); transition-delay: 0s; transition-duration: .4s; }
/* the text moves by exactly the window's travel (101% of the word plus the window's .08em sides),
   so it stands still while the window opens and none of it shows before */
.dw.arm .dw-t { transform: translateX(calc(101% + .1616em)); transition-delay: 0s; transition-duration: .4s; }
.dw-f { display: inline-block; white-space: nowrap; transform: none; transition: transform .75s cubic-bezier(.3, .7, .2, 1) .45s; }
.hl.a1 .dw-f[data-d="1"]:not(.dw-fd) { transform: translateX(calc(-1 * var(--s1, 0px))); transition-delay: 0s; transition-duration: .4s; }
.hl.a2 .dw-f[data-d="2"]:not(.dw-fd) { transform: translateX(calc(-1 * var(--s2, 0px))); transition-delay: 0s; transition-duration: .4s; }
.hl.a3 .dw-f[data-d="3"]:not(.dw-fd) { transform: translateX(calc(-1 * var(--s3, 0px))); transition-delay: 0s; transition-duration: .4s; }
.hl.a4 .dw-f[data-d="4"]:not(.dw-fd) { transform: translateX(calc(-1 * var(--s4, 0px))); transition-delay: 0s; transition-duration: .4s; }
/* words that only share the new word's line from 760 px (below, they start the next line) */
@media (min-width: 760px) {
  .hl.a1 .dw-fd[data-d="1"] { transform: translateX(calc(-1 * var(--s1, 0px))); transition-delay: 0s; transition-duration: .4s; }
  .hl.a2 .dw-fd[data-d="2"] { transform: translateX(calc(-1 * var(--s2, 0px))); transition-delay: 0s; transition-duration: .4s; }
  .hl.a3 .dw-fd[data-d="3"] { transform: translateX(calc(-1 * var(--s3, 0px))); transition-delay: 0s; transition-duration: .4s; }
  .hl.a4 .dw-fd[data-d="4"] { transform: translateX(calc(-1 * var(--s4, 0px))); transition-delay: 0s; transition-duration: .4s; }
}
/* site.js arms the headline at load with no transitions (see "dw-now" there) */
.hl.dw-now, .hl.dw-now *, .hl.dw-now *::after { transition: none !important; }
.hl .br-d { display: none; }
@media (min-width: 760px) { .hl .br-d { display: inline; } .hl .br-m { display: none; } }
/* before and after inside the example cards */
.ba { font-size: 14px; line-height: 1.45; display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; }
.ba s { color: var(--dim); text-decoration-color: var(--line-2); }
.ba ins { text-decoration: none; color: var(--deep); background: var(--pale); border-radius: 3px; padding: 0 3px; }
.ba .arrow { color: var(--blue); }

/* ---------------------------------------------------------------- statement + tiles */
.statement { font-size: clamp(22px, 2.8vw, 32px); line-height: 1.25; letter-spacing: -0.02em; max-width: 34ch; }
.statement span { color: var(--dim); }
.statement .key { font-style: normal; color: var(--blue); } /* blue only for the one takeaway phrase in each statement (user 16 Oct); Buch 400 only, so colour carries the emphasis */
.statement .nw { color: inherit; white-space: nowrap; } /* the blue phrase never starts with a lone word at a line end */
.statement.pretty { text-wrap: balance; text-wrap: pretty; } /* no stub last line; balance where pretty is unsupported */
.tiles { display: grid; gap: 16px; margin-top: 48px; }
@media (min-width: 760px) { .tiles { grid-template-columns: 1fr 1fr; gap: 20px; } }
.tile { border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); padding: 24px; display: grid; gap: 10px; align-content: start; }
.tile:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
/* Cube grid (assets/js/cubes.js): thin outlined cells, some filled in pale blues; cells tumble
   when the pointer sweeps across them, and keyboard focus sends a gentle ripple through. */
.blocks { position: relative; height: 150px; margin: 0 0 20px; border-radius: 6px; overflow: hidden; touch-action: pan-y; }
@media (min-width: 560px) { .blocks { height: 168px; } }
.tile h3 { font-size: 20px; letter-spacing: -0.015em; line-height: 1.3; }
.tile p { color: var(--muted); max-width: 52ch; }

/* ---------------------------------------------------------------- steps */
.steps { display: grid; border-top: 1px solid var(--line); }
@media (min-width: 860px) { .steps { grid-template-columns: repeat(3, 1fr); border-top: 0; } }
.steps li { padding: 24px 0; border-bottom: 1px solid var(--line); display: grid; gap: 8px; align-content: start; }
@media (min-width: 860px) { .steps li { padding: 4px 28px 8px; border-bottom: 0; border-left: 1px solid var(--line); } .steps li:first-child { padding-left: 0; border-left: 0; } }
.step-n { font-size: 13px; color: var(--deep); font-variant-numeric: tabular-nums; }
.steps h3 { font-size: 20px; line-height: 1.3; letter-spacing: -0.015em; }
.steps p { color: var(--muted); }

/* ---------------------------------------------------------------- contact + footer */
.contact { display: grid; gap: 28px; }
.contact .btn { white-space: normal; text-align: center; padding: 10px 20px; line-height: 1.3; }
.contact .sec-head { margin-bottom: 0; }
.contact-note { font-size: 15px; color: var(--muted); max-width: 60ch; }
.contact-cards { display: grid; gap: 16px; }
@media (min-width: 760px) { .contact-cards { grid-template-columns: 1fr 1fr; gap: 20px; } }
.contact-card { border: 1px solid var(--line); border-radius: var(--radius); padding: 22px 24px; background: var(--card); display: grid; gap: 12px; align-content: start; justify-items: start; }
.contact-card h3 { font-size: 20px; letter-spacing: -0.015em; }
.contact-card p { color: var(--muted); }
.contact-card .btn { margin-top: 4px; max-width: 100%; overflow-wrap: anywhere; }
.foot { border-top: 1px solid var(--line); padding: 32px 0 48px; display: grid; gap: 18px; }
.foot-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; }
.foot-row img { height: 22px; width: auto; }
.foot-links { display: flex; flex-wrap: wrap; gap: 6px 20px; font-size: 14px; }
.foot-links a { color: var(--muted); text-decoration: none; }
.foot-links a:hover { color: var(--text); text-decoration: underline; }

/* ---------------------------------------------------------------- inner pages (about, privacy) */
.page-head { padding: 56px 0 40px; }
@media (min-width: 960px) { .page-head { padding: 96px 0 56px; } }
.page-head h1 { font-size: clamp(30px, 4.4vw, 46px); line-height: 1.1; letter-spacing: -0.035em; max-width: 22ch; margin-top: 10px; }
.page-head .lede { margin-top: 16px; color: var(--muted); font-size: 18px; max-width: 58ch; }
.prose { border-top: 1px solid var(--line); padding: 40px 0 72px; max-width: 68ch; }
.prose h2 { font-size: 22px; letter-spacing: -0.015em; line-height: 1.3; margin: 36px 0 10px; }
.prose h2:first-child { margin-top: 0; }
.prose p, .prose li { color: var(--muted); }
.prose p + p { margin-top: 12px; }
.prose ul { display: grid; gap: 10px; }
.prose li { padding-left: 18px; position: relative; }
.prose li::before { content: ""; position: absolute; left: 0; top: 10px; width: 6px; height: 6px; border-radius: 50%; border: 1px solid var(--blue); }
.prose strong { font-weight: var(--weight); color: var(--text); }
.prose a { color: var(--deep); text-underline-offset: 3px; }
.callout { padding: 12px 16px; border: 1px dashed var(--line-2); border-radius: 8px; margin-bottom: 24px; }

/* ---------------------------------------------------------------- intro (first visit per session) */
/* The overlay is cream from the first paint; assets/js/intro.js draws the animation into it.
   If the script never runs, the fallback fades the overlay out after 4.5 s. */
.intro { display: none; }
html.uc-intro .intro { display: block; position: fixed; inset: 0; z-index: 100; overflow: hidden; background: var(--bg); cursor: pointer; animation: intro-fallback .4s ease 4.5s forwards; }
html.uc-intro .intro.running { animation: none; }
.intro svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* the intro's first frame (assets/img/intro-first.webp, the live t = 0 frame at 1440 x 900), so the
   very first paint already shows the hero field's scattered cubes; it drifts right at about the
   cubes' mean speed (about 2.7vw a second) until intro.js takes over and fades it out */
.intro .uci-first { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: cover; pointer-events: none; animation: uci-first-drift 6s linear both; }
@keyframes uci-first-drift { to { transform: translateX(16vw); } }
@keyframes intro-fallback { to { opacity: 0; visibility: hidden; } }
html.uc-intro-done .intro { display: none; }

/* ---------------------------------------------------------------- motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
  .intro { display: none !important; }
}
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
