/* ══ sota.bot ═════════════════════════════════════════════════════════════════
   One screen: a mark, a headline, a lead, a button, a phone, a switcher.

   ⚠ NOTHING IN HERE IS WABI'S. Not the face, not the ground, not the ink, not the
   radius scale. The whole point of this rig is that a reader judges the MESSAGE
   without recognising whose message it is, so a palette anybody could place is a
   bug in the test, not a styling preference.

   ⚠ AND THERE IS ONE ACCENT, USED ONCE. It marks which pole of the doing/creating
   axis the current message argues from, which is the one thing on the page that is
   about the rig rather than about the product.
   ────────────────────────────────────────────────────────────────────────────── */

/* ⚠ ONE VARIABLE FILE CARRIES 400-900. Declared as a range, or the browser
   synthesises a fake bold from the 400 instance and the headline comes out smeared
   at exactly the size it matters most. */
@font-face {
  font-family: 'Schibsted';
  src: url('../fonts/Schibsted.woff2') format('woff2');
  font-weight: 400 900;
  font-style: normal;
  font-display: block;   /* block, not swap: the headline is FITTED, and fitting a
                            fallback then re-fitting the real face is the jump the
                            boot class exists to prevent */
}

:root {
  --paper:  #F5F4F1;
  --ink:    #111310;
  --muted:  #6B6F69;
  --hair:   rgba(17, 19, 16, 0.12);
  --accent: #D8452A;

  /* the phone's own ink, which is not the page's — a screen is emissive and a page
     is not, so the two grounds cannot be the same colour */
  --scr:      #FFFFFF;
  --scr-ink:  #14171A;
  --scr-mute: #8A9099;
  --scr-hair: rgba(20, 23, 26, 0.09);

  --r: 14px;
}

* { box-sizing: border-box; }

html, body { height: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Schibsted', system-ui, -apple-system, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;              /* one screen, and it does not scroll */
  -webkit-tap-highlight-color: transparent;
}

/* ⚠ THE BOOT CLASS HIDES ONLY WHAT IS ABOUT TO BE MEASURED. Hiding the whole page
   means a blank screen for as long as one font takes to arrive, so the mark and the
   switcher paint immediately and the headline waits for its fit. */
html.boot .head,
html.boot .lead,
html.boot .phonewrap { visibility: hidden; }

/* ══ THE MARK ═══════════════════════════════════════════════════════════════════
   See the note over the markup in index.html for what unfurls and why. */
.mark {
  position: fixed;
  top: 26px; left: 30px;
  z-index: 10;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--ink);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.014em;
  line-height: 1;
}
.mk-sr {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.mk-logo { display: block; width: 22px; height: 22px; flex: none; }
.mk-logo svg { display: block; width: 100%; height: 100%; }
.mk-head { fill: var(--ink); }
.mk-eyes { fill: var(--paper); }
/* the eyes lean a hair toward the words as they arrive — the only thing on the mark
   that moves besides the type, and it is 1.5% of the box */
.mk-eyes { transform: translateX(0); transition: transform 700ms cubic-bezier(0.42, 0, 0.12, 1); }
.mark:hover .mk-eyes,
.mark:focus-visible .mk-eyes { transform: translateX(4px); }

.mk { display: inline-flex; align-items: baseline; }

/* ⚠ THE WIDTH IS AN `fr`, NOT A `max-width`. A max-width transition needs a number
   big enough for the longest word, and then the easing is wrong for every shorter
   one — it reaches the real width early and spends the rest of the duration doing
   nothing, which is exactly the "nearly smooth but slightly dead" feeling.
   `grid-template-columns: 0fr → 1fr` interpolates to the CONTENT's own width, so
   the curve is the whole travel and there is no magic number to keep in step with
   the words. Ported from joonas.wtf's mark, whose note this is. */
.mk-grow {
  display: inline-grid;
  grid-template-columns: 0fr;
  /* ⚠ NOT an expo-out. cubic-bezier(0.22,1,0.36,1) puts most of its travel in the
     first fifth, so the box springs open and sits there while the ink is still
     arriving. A curve with a gentle HEAD as well as a gentle tail opens the box at
     the pace the words fill it. */
  transition: grid-template-columns 640ms cubic-bezier(0.42, 0, 0.12, 1);
}
/* ⚠ `.bot` RUNS THE SAME GRID BACKWARDS — 1fr at rest, 0fr on hover. It is the one
   group that is not an initial of the tagline, so it has nothing to grow into and
   left standing the mark unfurls to "state of the art bot", a phrase nobody wrote.
   ⚠ AND IT COLLAPSES RATHER THAN FADING. Faded it leaves four characters' worth of
   hole on the end of the line, which reads as the tagline having been cut off.
   ⚠ AT REST IT IS GREY: `sota` is the name and `.bot` is the address it lives at,
   and setting both in one weight makes the reader parse eight characters where
   there are four. */
.mk-tail {
  display: inline-grid;
  grid-template-columns: 1fr;
  color: var(--muted);
  transition: grid-template-columns 640ms cubic-bezier(0.42, 0, 0.12, 1),
              color 200ms ease;
}
.mk-in {
  min-width: 0;
  overflow: hidden;
  white-space: pre;      /* the spaces belong to the words that arrive */
}
.mk-in i {
  font-style: inherit;
  display: inline-block;
  opacity: 0;
  transform: translateX(-0.2em);
  filter: blur(2.5px);
  /* the letters run a touch faster than the box that holds them, and each waits its
     turn — so the tagline reads as being written rather than as a panel opening */
  transition:
    opacity   280ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 440ms cubic-bezier(0.22, 1, 0.36, 1),
    filter    280ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* focus counts too — it is the only way a keyboard ever sees the tagline */
.mark:hover .mk-grow,
.mark:focus-visible .mk-grow { grid-template-columns: 1fr; }
.mark:hover .mk-tail,
.mark:focus-visible .mk-tail { grid-template-columns: 0fr; }

/* ⚠ COLLAPSING RUNS IN REVERSE — the last letter leaves first. Played forwards on
   the way out the words appear to be written again as they disappear, which reads
   as a stutter. 9 is the last index. */
.mk-in i { transition-delay: calc((9 - var(--i)) * 9ms); }
.mark:hover .mk-in i,
.mark:focus-visible .mk-in i {
  opacity: 1;
  transform: none;
  filter: blur(0);
  /* the stagger has to FIT INSIDE the box's own travel: 9 letters at 24ms is 216ms
     plus a 280ms fade lands at ~500ms against the box's 640 — so the words finish
     being written a beat before the box stops moving, which is the order that reads
     as one gesture */
  transition-delay: calc(var(--i) * 24ms);
}

/* ⚠ ONLY WHERE THERE IS A HOVER AND ROOM FOR IT. On a phone the tagline is wider
   than the screen, and nothing on a touch device can trigger it anyway. */
@media (hover: none), (max-width: 719px) {
  .mk-grow { display: none; }
}

/* ══ THE BACKDROP ═══════════════════════════════════════════════════════════════
   ⚠ IT IS BEHIND THE PAGE AND INERT. `z-index: 0` under a stage at 1, and
   `pointer-events: none` throughout — a full-bleed layer that answers the pointer is
   a layer that eats every click on the thing in front of it, which is the failure
   that renders perfectly and cannot be seen. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.backdrop > * { position: absolute; inset: 0; width: 100%; height: 100%; }
#orbit { display: none; }
html[data-bg='orbit'] #orbit { display: block; }

.props { display: none; }
html[data-bg='props'] .props { display: block; }
.props img {
  position: absolute;
  /* placed from the persona's own x/y/s/r — see js/personas.js. `s` is a share of
     the SHORT side, so a prop is the same size on a tall window as on a wide one. */
  width: calc(var(--s) * min(100vw, 100vh) / 100);
  height: auto;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1%);
  transform: translate(-50%, -50%) rotate(calc(var(--r) * 1deg));
  /* ⚠ wabi.ai's OWN prop shadow, read off its hero — the same two drop-shadows the
     phone carries. Baked into the bitmap it would be a grey rectangle on a cream
     page; in CSS it follows the cut-out's alpha. */
  filter: drop-shadow(rgba(0, 0, 0, 0.086) 0px 14px 24px)
          drop-shadow(rgba(0, 0, 0, 0.06) 0px 4px 8px);
  opacity: 0;
  transition: opacity 420ms ease;
}
html[data-bg='props'] .props img { opacity: 1; }

/* ══ THE STACK, DECLARED ONCE ═══════════════════════════════════════════════════
   ⚠ AND IT HAS TO BE, because giving two of these the SAME z-index does not leave
   them alone — it hands the decision to DOM ORDER. `.stage` and `.mark` both at 1
   put the stage on top (it comes later in the document), and the stage is a
   full-height grid that covers the corner the mark sits in: the wordmark rendered
   perfectly, in the right place, at full opacity, and `elementFromPoint` at its own
   centre returned the stage. It could not be hovered and it could not be clicked.
   That is the failure no screenshot can show, and it is why every click in
   `tools/verify.mjs` is hit-tested first.
      0  the backdrop
      1  the stage
      2  the chrome — the mark, the top CTA, the rig
   Nothing on this page may use a z-index that is not on this list. */
.backdrop { z-index: 0; }
.stage    { position: relative; z-index: 1; }
.mark, .topcta, .rig { position: fixed; z-index: 2; }

/* ══ THE TOP CTA ════════════════════════════════════════════════════════════════
   ⚠ QUIET ON PURPOSE — see the note over the markup. The hero button is the solid
   one; this is an outline, so the two never compete and the persona's own verb is
   still the loudest thing under the headline. */
.topcta {
  position: fixed;
  top: 22px; right: clamp(18px, 3vw, 34px);
  z-index: 10;
  display: inline-flex;
  align-items: center;
  /* ⚠ 40, and a real one: this is a corner control on a phone too. */
  min-height: 40px;
  padding: 0 18px;
  border-radius: 999px;
  border: 1px solid var(--hair);
  background: rgba(255, 255, 255, 0.55);
  color: var(--ink);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.006em;
  backdrop-filter: blur(10px) saturate(1.2);
  transition: background 180ms ease, transform 180ms cubic-bezier(0.22, 1, 0.36, 1), border-color 180ms ease;
}
.topcta:hover { background: #fff; border-color: rgba(17, 19, 16, 0.22); transform: translateY(-1px); }
.topcta:active { transform: translateY(0); }

/* ══ THE PAGE ═══════════════════════════════════════════════════════════════════ */
.stage {
  height: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(24px, 5vw, 84px);
  padding: 96px clamp(30px, 5vw, 88px) 132px;
}

.copy { min-width: 0; max-width: 640px; justify-self: end; width: 100%; }


/* ⚠ THE SIZE IS WRITTEN BY THE FIT, NOT BY THIS RULE. The clamp is only what the
   first paint needs and a ceiling for the search; app.js measures the real thing.
   A headline of four short words and one of six long ones do not want the same
   size, and the persona chooses which it is. */
.head {
  margin: 0;
  font-size: clamp(38px, 6.4vw, 92px);
  font-weight: 700;
  line-height: 0.99;
  letter-spacing: -0.032em;
  text-wrap: balance;
}

.lead {
  margin: clamp(18px, 2.4vh, 30px) 0 0;
  max-width: 30em;                 /* the measure, not the column — a lead set the
                                      full width of a wide screen is unreadable */
  font-size: clamp(15px, 1.15vw, 18.5px);
  line-height: 1.5;
  color: var(--muted);
  letter-spacing: -0.004em;
}

.act {
  margin-top: clamp(22px, 3.2vh, 38px);
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.cta {
  appearance: none;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font: inherit;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.006em;
  /* ⚠ 48, not 44. This is the only action on the page and it is the one measurement
     that must not be tight. */
  min-height: 48px;
  padding: 0 26px;
  cursor: pointer;
  transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1), opacity 180ms ease;
}
.cta:hover { transform: translateY(-1.5px); }
.cta:active { transform: translateY(0); opacity: 0.86; }
.act-note { font-size: 13px; color: var(--muted); }

/* ══ THE PHONE ══════════════════════════════════════════════════════════════════
   Drawn, never photographed — see the note over the markup. */
.phonewrap {
  display: flex;
  justify-content: flex-start;
  min-width: 0;
  /* ⚠ THE PERSPECTIVE IS ON THE WRAPPER, NOT IN THE TRANSFORM. Written as
     `transform: perspective(1200px) rotateY(…)` the vanishing point is the PHONE's
     own centre, so the frame turns about itself and the picture never reads as an
     object standing in a room. On the parent it is the room's vanishing point, and
     the phone is a thing inside it.
     1200px is the new website's own number (`page.tsx`, the card stack). */
}

/* ⚠ HEIGHT-LED, because the window's height is what runs out first — and the width
   follows from the FRAME'S OWN ASPECT (760 × 1562 = 0.48655), never from a second
   number that has to be kept in step with the image. */
.phone {
  --ph-h: min(74vh, 680px);
  height: var(--ph-h);
  width: calc(var(--ph-h) * 0.48655);
  position: relative;
  flex: none;
  /* ══ THE TILT ══════════════════════════════════════════════════════════════
     ⚠ IN-PLANE, AND THE 3D VERSION WAS THE BUG. This was `perspective(1200px)
     rotateY(-9deg)` first — the card-stack tilt out of the new website's source —
     and it read as FAKE for a reason worth writing down: that transform turns a
     CARD somebody is holding, and what is being turned here is a PHOTOGRAPH of a
     phone. A flat image rotated in 3D does not look like a phone turning, it looks
     like a picture of a phone turning — the bezel keeps its painted width, the side
     rail never comes into view, and every highlight stays exactly where it was
     printed. Nothing about the object answers the rotation.

     MEASURED off wabi.ai's own hero at 1440×900, reading the computed transform
     back off the phone element: it is `rotate(4deg)`. Plain, in-plane, no
     perspective anywhere — the object is simply standing at an angle, which is
     something a photograph can be perfectly honest about.

     `--tilt` is written every frame by the spring in app.js; the value here is only
     what the first paint needs. */
  transform: rotate(var(--tilt, 4deg));
  /* ⚠ THE SHADOW IS A `filter`, NOT A `box-shadow`. A box-shadow is the shape of the
     BOX, and this phone's box is a rectangle while the thing in it has rounded
     corners and a transparent surround — so a box-shadow draws a hard rectangle
     behind a rounded object. A drop-shadow follows the frame's own alpha. */
     ⚠ AND THE SHADOW IS wabi.ai's OWN, read off the same page: two drop-shadows at
     `rgba(0,0,0,.086) 0 14px 24px` and `rgba(0,0,0,.06) 0 4px 8px`. What was here
     before was three times the opacity at two and a half times the blur, which
     against a page this light is not a soft shadow but a dark smear — and it was
     the other half of why the phone looked pasted on. */
  filter: drop-shadow(rgba(0, 0, 0, 0.086) 0px 14px 24px)
          drop-shadow(rgba(0, 0, 0, 0.06) 0px 4px 8px);
  will-change: transform;
}

/* the frame paints OVER the screen, and its opaque bezel is what trims it */
.phone > .frame {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.screen {
  position: absolute;
  z-index: 1;
  /* see the note over the markup for why this is looser than the glass */
  inset: 0.9% 3.3% 1.0% 3.25%;
  border-radius: 13.5% / 6.4%;
  background: var(--scr);
  color: var(--scr-ink);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* ⚠ THE CONTAINER IS THE SCREEN, NOT THE PHONE. Every length inside is a share of
     the glass you can actually see, which is what those numbers were chosen against
     — on the phone it would include the bezel, and the whole design would be ~7%
     small in a box nobody can put anything in. */
  container-type: inline-size;
}

.scr-top {
  padding: 13cqw 7cqw 4cqw;
  flex: none;
}
.scr-app {
  font-size: 7.4cqw;
  font-weight: 700;
  letter-spacing: -0.028em;
}
.scr-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 2cqw 7cqw 0;
  overflow: hidden;
}

/* — the hero card, on every shape but the chat — */
.hero {
  border-radius: 5cqw;
  background: #F1F2F0;
  padding: 6cqw 5.4cqw 5.4cqw;
  display: flex;
  flex-direction: column;
  gap: 1.4cqw;
  margin-bottom: 3cqw;
}
.hero-b { font-size: 13cqw; font-weight: 700; letter-spacing: -0.04em; line-height: 0.9; }
.hero-s { font-size: 3.7cqw; color: var(--scr-mute); letter-spacing: 0.002em; }

/* — the list shape — */
.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 3cqw;
  padding: 4cqw 0;
  border-bottom: 1px solid var(--scr-hair);
}
.row:last-child { border-bottom: 0; }
.row-l { display: flex; flex-direction: column; gap: 0.7cqw; min-width: 0; }
.row-t { font-size: 4.2cqw; letter-spacing: -0.012em; }
.row-s { font-size: 3.3cqw; color: var(--scr-mute); letter-spacing: 0.004em; }
.row-v { font-size: 4.2cqw; font-weight: 600; color: var(--scr-mute); white-space: nowrap; }

/* — the tiles shape — */
.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 3cqw; }
.tile {
  border-radius: 4.4cqw;
  background: #F1F2F0;
  padding: 4.6cqw;
  min-height: 24cqw;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.9cqw;
}
.tile-l { font-size: 6.6cqw; font-weight: 700; letter-spacing: -0.03em; line-height: 1; }
.tile-s { font-size: 3.4cqw; color: var(--scr-mute); letter-spacing: 0.01em; }

/* — the chat shape — */
/* ⚠ THE BODY BECOMES A BOTTOM-ALIGNED COLUMN for this kind only. A chat whose newest
   turn floats at the top of an empty screen is the one arrangement no messaging app
   has ever had. */
.scr-body[data-kind='chat'] { display: flex; flex-direction: column; justify-content: flex-end; padding-bottom: 3cqw; }
.chat { display: flex; flex-direction: column; gap: 2.4cqw; }
.bub {
  max-width: 80%;
  border-radius: 4.6cqw;
  padding: 3.4cqw 4.2cqw;
  font-size: 3.9cqw;
  line-height: 1.36;
  letter-spacing: -0.01em;
}
.bub.you { align-self: flex-end; background: var(--scr-ink); color: #fff; border-bottom-right-radius: 1.4cqw; }
.bub.bot { align-self: flex-start; background: #F1F2F0; border-bottom-left-radius: 1.4cqw; }

/* — the bar, which is the same on every persona because the gesture is —
   ⚠ IT SITS ON THE SCREEN'S OWN GROUND, not on a tinted panel. A bar the reader
   reads as chrome is a bar they do not read as the thing you type into. */
.scr-bar {
  flex: none;
  margin: 0 5.4cqw 7cqw;
  border: 1px solid var(--scr-hair);
  border-radius: 999px;
  min-height: 12.4cqw;
  display: flex;
  align-items: center;
  gap: 2.4cqw;
  padding: 0 2cqw 0 5cqw;
}
.scr-ask {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 3.9cqw;
  color: var(--scr-mute);
  letter-spacing: -0.008em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.scr-send {
  flex: none;
  width: 9cqw; height: 9cqw;
  border-radius: 999px;
  background: var(--scr-ink);
  position: relative;
}
.scr-send::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 2.4cqw; height: 2.4cqw;
  border: solid #fff;
  border-width: 1.5px 1.5px 0 0;
  transform: translateY(0.35cqw) rotate(-45deg);
}
/* ⚠ NO DRAWN HOME INDICATOR ANY MORE — the real frame has one, and two of them is
   a photograph of a phone with a second phone's chrome printed on it. The bar keeps
   the room the indicator needs instead. */

/* ══ THE RIG ════════════════════════════════════════════════════════════════════
   ⚠ THE SWITCHER TAKES ITS OWN LINE ABOVE THE READOUT. Five names beside a line of
   prose is a row that wraps at the first narrow window, and a wrapped pill reads as
   broken rather than as full — the 999px radius that makes a pill makes a wrapped
   one a lozenge with a crescent of dead glass round it. */
.rig {
  position: fixed;
  right: clamp(18px, 3vw, 34px);
  bottom: clamp(16px, 2.4vw, 26px);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 9px;
  max-width: calc(100vw - 40px);
}
.pill {
  display: flex;
  gap: 2px;
  padding: 4px;
  border-radius: 999px;
  background: rgba(17, 19, 16, 0.055);
  border: 1px solid var(--hair);
}
.pill button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.004em;
  border-radius: 999px;
  /* ⚠ A FLOOR, NOT MORE PADDING. `Main` measured 43px against a 44 target — a floor
     costs the row one pixel where widening everyone's padding would cost fifty and
     push the row into a wrap. */
  min-width: 44px;
  min-height: 30px;
  padding: 0 11px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 160ms ease, background 160ms ease;
}
/* ⚠ SMALLER TYPE, NOT A SMALLER TARGET. This is the secondary switch and it should
   read as one, but a control is a control: the floor stays where the message pill's
   is and only the type steps down. */
.pill--sm button { font-size: 11.5px; min-height: 30px; min-width: 44px; padding: 0 10px; }
.pill button:hover { color: var(--ink); }
.pill button[aria-pressed='true'] {
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(17, 19, 16, 0.1), 0 0 0 1px var(--hair);
}

.readout {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--muted);
  text-align: right;
  max-width: 44ch;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.ax {
  flex: none;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 10px;
  color: var(--accent);
}

/* ══ NARROW ═════════════════════════════════════════════════════════════════════
   ⚠ THE PHONE GOES, IT DOES NOT SHRINK. Below the point where two columns stop
   working, a phone scaled to fit beside the copy is a thumbnail nobody can read the
   screen of — and the screen is half the message. The copy is what a narrow reader
   is there for. */
@media (max-width: 900px) {
  .stage {
    grid-template-columns: minmax(0, 1fr);
    padding: 86px clamp(22px, 6vw, 44px) 118px;
    align-content: center;
  }
  .copy { justify-self: start; max-width: 34em; }
  .phonewrap { display: none; }
  /* ⚠ AND THE PROPS GO WITH IT. They are placed in the phone's half of the stage;
     with the phone gone there is no such half, and every one of them would be lying
     on the copy — which is the whole of what a narrow reader came for. */
  html[data-bg='props'] .props { display: none; }
  .head { font-size: clamp(34px, 9.4vw, 62px); }
  .rig { left: clamp(18px, 6vw, 34px); align-items: flex-start; }
  .pill { flex-wrap: wrap; }
  .readout { text-align: left; justify-content: flex-start; }
}

/* ⚠ REDUCED MOTION TAKES THE TRANSITIONS OFF, NOT THE MECHANISM. The tagline still
   unfurls on hover — that is a response to an action — it just arrives at once. */
@media (prefers-reduced-motion: reduce) {
  .mk-grow, .mk-tail, .mk-in i, .mk-eyes, .cta, .pill button { transition-duration: 1ms !important; }
}
