/*
  EpiSeiz product page.

  The tokens below are lifted from the app's `src/theme/tokens.ts` and
  `theme.ts` rather than invented for the web. That is deliberate: the page and
  the app should look like the same object, and the rules the design system
  sets are the ones that keep this restrained instead of shouty.

  Three of those rules do real work here and are easy to erode:

  - The primary is ink, not a colour. There is no brand blue and no brand
    green. Buttons are near-black on bone.
  - Jade has a budget. It is the mark, the live dot, and the word "ok". It is
    never a fill, never a heading, never a section background.
  - Alert red is reserved. It appears exactly twice on this page: the moment
    the detector fires on the trace, and the live-alert dot at 3am. If it ever
    creeps into a third place, one of them is wrong.

  Scoped to this file. The studio page at `/` is a different design system and
  the two share only the shell.
*/

:root {
  /* Stone. Warm neutral, never cold, never pure grey. */
  --paper: #FCFCFB;
  --card: #FFFFFF;
  --sunken: #F8F8F6;
  --raised: #F2F2EF;

  --ink: #1C1C1A;
  --ink-deep: #111110;
  --body: #4A4A45;
  --muted: #6A6A64;
  --faint: #8B8B85;

  --hair: rgba(28, 28, 26, 0.075);
  --hair-firm: rgba(28, 28, 26, 0.13);
  --hair-strong: rgba(28, 28, 26, 0.22);

  --jade: #0F8C71;
  --jade-quiet: #0B6E59;
  --alert: #D9452D;

  /* The night band. Always dark, in both schemes: it is 3am either way. */
  --night: #111110;
  --night-raised: #1C1C1A;
  --night-hair: rgba(255, 255, 255, 0.12);
  --night-text: #F7F7F5;
  --night-body: rgba(255, 255, 255, 0.7);
  --night-faint: rgba(255, 255, 255, 0.46);
  --night-jade: #6BC6AB;
  --night-alert: #F0907F;

  --display: 'Manrope', 'Helvetica Neue', Arial, sans-serif;
  --sans: 'IBM Plex Sans', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, Menlo, monospace;

  --shell: 1140px;
  --gutter: clamp(22px, 5vw, 44px);

  /* No bounce, no spring. Ported from tokens.ts `motion`. */
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0D0D0C;
    --card: #151514;
    --sunken: #1C1C1A;
    --raised: #1C1C1A;

    --ink: #F7F7F5;
    --ink-deep: #FFFFFF;
    --body: #D3D3CE;
    --muted: #A6A6A0;
    --faint: #878781;

    --hair: rgba(255, 255, 255, 0.085);
    --hair-firm: rgba(255, 255, 255, 0.15);
    --hair-strong: rgba(255, 255, 255, 0.26);

    /* Jade and alert both lighten on dark, per theme.ts `darkTheme`. */
    --jade: #6BC6AB;
    --jade-quiet: #33A98A;
    --alert: #E56A55;

    /* The band lifts away from the page instead of sinking into it. */
    --night: #1C1C1A;
    --night-raised: #2E2E2B;
  }
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--body);
  font: 400 16.5px/1.62 var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, p, figure, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; text-underline-offset: 3px; text-decoration-thickness: 1px; }

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  border-radius: 4px;
}

.shell {
  max-width: var(--shell);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 18px;
  border-radius: 0 0 12px 0;
  z-index: 10;
}
.skip-link:focus { left: 0; }

/* Type scale. Ratios sit at or above 1.25 between steps; the display face is
   Manrope at the app's -2.6% tracking, which is tight enough that it needs the
   fluid clamp to stay readable at 320px. */
.display {
  font: 800 clamp(38px, 6.6vw, 74px)/1.03 var(--display);
  letter-spacing: -0.032em;
  color: var(--ink);
  text-wrap: balance;
}
.h2 {
  font: 700 clamp(28px, 3.9vw, 44px)/1.1 var(--display);
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}
.h3 {
  font: 700 clamp(20px, 2.2vw, 25px)/1.24 var(--display);
  letter-spacing: -0.026em;
  color: var(--ink);
}
.h4 {
  font: 600 17px/1.35 var(--display);
  letter-spacing: -0.014em;
  color: var(--ink);
}
.lede {
  font-size: clamp(17.5px, 2vw, 21px);
  line-height: 1.55;
  max-width: 34ch;
  text-wrap: pretty;
}
.prose { max-width: 62ch; text-wrap: pretty; }
.prose + .prose { margin-top: 15px; }
.muted { color: var(--muted); }
.faint { color: var(--faint); }

.overline {
  font: 600 11.5px/1.1 var(--sans);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.mono { font: 500 13px/1.4 var(--mono); }

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--hair);
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  height: 62px;
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  font: 700 19px/1 var(--display);
  letter-spacing: -0.034em;
  color: var(--ink);
}
.wordmark svg { display: block; }
.header-link {
  font: 500 14px/1 var(--sans);
  color: var(--muted);
  text-decoration: none;
}
.header-link:hover { color: var(--ink); }

/* ------------------------------------------------------------------ hero */

.hero { padding: clamp(56px, 9vw, 104px) 0 clamp(28px, 4vw, 44px); }
.hero .overline { display: block; margin-bottom: 22px; }
.hero .display { max-width: 15ch; }
.hero .lede { margin-top: 24px; }

.hero-status {
  margin-top: 32px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  font-size: 14.5px;
  color: var(--muted);
}
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 11px;
  border: 1px solid var(--hair-firm);
  border-radius: 999px;
  background: var(--card);
  font: 500 13.5px/1 var(--sans);
  color: var(--ink);
}
.dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--jade);
  flex: 0 0 auto;
}

/* ----------------------------------------------------------------- trace */

/*
  The one piece of artwork on the page, and it is not decoration: it is a
  90-second accelerometer trace generated from the frequencies in
  docs/DETECTION.md. Ordinary movement, the tonic stiffening, then the clonic
  phase chirping 4.8 Hz down to 2.1 Hz, then post-ictal stillness. The red mark
  is where the detector is finally willing to speak, 15 seconds in.
*/
.trace-figure {
  margin-top: clamp(36px, 6vw, 64px);
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  padding: 30px 0 22px;
}
/*
  `preserveAspectRatio="none"` plus an explicit fluid height, rather than
  height:auto. A 1200-unit-wide viewBox at phone width is 62px tall, which
  squashes the whole event into a smudge; letting the vertical scale run free
  keeps it readable at every width. Strokes are pinned with
  `vector-effect` so the stretch never thickens or thins a line.
*/
.trace {
  display: block;
  width: 100%;
  height: clamp(150px, 17vw, 215px);
  overflow: visible;
}

.trace-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px 22px;
  margin-top: 14px;
  font: 500 12px/1.4 var(--mono);
  color: var(--faint);
}
.legend-key {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 3px;
  vertical-align: -1px;
}
/* Each swatch wraps with its own label instead of stranding one on a line
   of its own at 320px. */
.legend-item { display: inline-flex; align-items: center; gap: 7px; }
.legend-fire { background: var(--alert); border-radius: 999px; width: 9px; height: 9px; }
.legend-band { background: var(--hair); border: 1px solid var(--hair-firm); }

.trace-line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 0.85;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.62;
  vector-effect: non-scaling-stroke;
}
/* The envelope carries the shape of the event; the line inside it is the real
   signal, and at this width it reads as texture rather than as countable
   peaks. That is what the two magnified windows underneath are for. */
.trace-env {
  fill: var(--ink);
  fill-opacity: 0.07;
  stroke: var(--ink);
  stroke-width: 1.1;
  stroke-opacity: 0.5;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.trace-band { fill: var(--hair); }
.trace-fire { stroke: var(--alert); stroke-width: 1.8; vector-effect: non-scaling-stroke; }
.trace-fire-dot { fill: var(--alert); }

/*
  Two magnified windows, side by side and at the same vertical scale, because
  the slowing is the whole claim and it cannot be seen in the panel above:
  forty-four seconds of 2-6 Hz across 1200px is about four pixels per cycle.
*/
.trace-details {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
  gap: 14px 34px;
  margin-top: 22px;
  max-width: 820px;
}
.trace-win {
  background: var(--sunken);
  border: 1px solid var(--hair-firm);
  border-radius: 12px;
  padding: 10px 14px 12px;
}
.trace-win-label {
  font: 500 12px/1 var(--mono);
  color: var(--faint);
  margin-bottom: 8px;
}
.trace-win svg { display: block; width: 100%; height: auto; }
.trace-win-line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.trace-label {
  font: 500 12px/1 var(--mono);
  fill: var(--faint);
  letter-spacing: 0.01em;
}
.trace-label.is-fire { fill: var(--alert); }

/*
  The signal arriving. `pathLength="1"` normalises the dash maths: the real
  path is tens of thousands of user units long and a hard-coded dasharray
  leaves a gap partway through, which reads as the trace stopping dead.
*/
@media (prefers-reduced-motion: no-preference) {
  .trace-line {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: draw 2.8s var(--ease) 0.15s forwards;
  }
  .trace-env, .trace-fire, .trace-legend, .trace-win {
    opacity: 0;
    animation: fade 0.6s var(--ease) forwards;
  }
  .trace-env { animation-delay: 0.15s; }
  .trace-fire, .trace-legend { animation-delay: 1.7s; }
  .trace-win { animation-delay: 2.4s; }
  .trace-win:last-child { animation-delay: 2.55s; }
}
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fade { to { opacity: 1; } }

.trace-caption {
  margin-top: 20px;
  max-width: 62ch;
  font-size: 14px;
  line-height: 1.55;
  color: var(--muted);
  text-wrap: pretty;
}

/* -------------------------------------------------------------- sections */

.section { padding: clamp(64px, 9vw, 116px) 0; }
.section-tight { padding: clamp(48px, 6vw, 76px) 0; }
.section + .section { border-top: 1px solid var(--hair); }

.section-head { max-width: 44ch; }
.section-head .overline { display: block; margin-bottom: 18px; }
.section-head .h2 + .prose { margin-top: 20px; }

/*
  A two-column split rather than a card grid. The heading holds the left rail
  and the detail runs down the right, which keeps long sections readable
  without wrapping every paragraph in a box.
*/
.split {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(32px, 6vw, 88px);
  align-items: start;
}
/* Two peers rather than a heading and its detail, so the columns are even. */
.duo { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; gap: 32px; }
}

/* Hairline rows, the same affordance the app uses for lists. Not cards. */
.rows { border-top: 1px solid var(--hair); }
.rows > li {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 18px;
  padding: 20px 0;
  border-bottom: 1px solid var(--hair);
}
.rows .h4 {
  margin-bottom: 5px;
  font: 600 15.5px/1.35 var(--sans);
  letter-spacing: -0.005em;
}
.rows p { font-size: 15px; color: var(--muted); }
.row-glyph { color: var(--ink); padding-top: 2px; }
.row-glyph svg { display: block; }

/* --------------------------------------------------------- the limit note */

/*
  Set as a quotation rather than a warning box. It is the most important
  sentence on the page and a yellow alert panel would make it look like fine
  print to be dismissed.
*/
.limit {
  border-left: none;
  padding: clamp(30px, 4vw, 44px) 0 0;
  margin-top: clamp(30px, 4vw, 40px);
  border-top: 1.5px solid var(--ink);
}
.limit > p:first-child {
  font: 600 clamp(19px, 2.4vw, 25px)/1.42 var(--display);
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 30ch;
  text-wrap: balance;
}
.limit .prose { margin-top: 18px; font-size: 15.5px; }

/* ------------------------------------------------------------ night band */

.night {
  background: var(--night);
  color: var(--night-body);
  padding: clamp(72px, 10vw, 132px) 0;
}
.night .h2, .night .h3, .night .h4 { color: var(--night-text); }
.night .overline { color: var(--night-faint); }
.night .faint { color: var(--night-faint); }
.night .muted { color: var(--night-body); }

.night-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
  gap: clamp(40px, 7vw, 92px);
  align-items: center;
}
@media (max-width: 900px) {
  .night-grid { grid-template-columns: 1fr; }
}

/* The 30-second sequence. A timeline with real timestamps, because the
   30 seconds is the product's single most reassuring fact. */
.steps { margin-top: 40px; }
.steps > li {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr);
  gap: 20px;
  padding: 18px 0;
  border-top: 1px solid var(--night-hair);
}
.steps time {
  font: 500 13px/1.5 var(--mono);
  color: var(--night-faint);
  padding-top: 2px;
  font-variant-numeric: tabular-nums;
}
.steps .h4 {
  margin-bottom: 4px;
  font: 600 15.5px/1.35 var(--sans);
  letter-spacing: -0.005em;
}
.steps p { font-size: 15px; color: var(--night-body); }

/*
  The lock screen, drawn rather than screenshotted, so it stays crisp and
  restyles with the tokens instead of going stale at the next redesign.
*/
.phone {
  position: relative;
  width: 100%;
  max-width: 302px;
  margin-inline: auto;
  aspect-ratio: 9 / 16.4;
  border-radius: 44px;
  background: #0A0A09;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 40px 80px rgba(0, 0, 0, 0.45);
  padding: 26px 16px 20px;
  display: flex;
  flex-direction: column;
  color: #F7F7F5;
  overflow: hidden;
}
.phone-clock {
  text-align: center;
  font: 300 60px/1 var(--display);
  letter-spacing: -0.03em;
  margin-top: 10px;
}
.phone-date {
  text-align: center;
  font: 400 13px/1 var(--sans);
  color: rgba(255, 255, 255, 0.5);
  margin-top: 10px;
}

/*
  THE SEQUENCE.

  Four states on one twelve-second loop, three seconds each, cross-fading in
  place. Everything a visitor has to believe about this product happens inside
  thirty seconds, and a paragraph describing thirty seconds is a weaker
  argument than watching them go by. The step list beside the phone runs off
  the same clock, so reading and watching stay in step.

  All of it is CSS. The site ships no JavaScript at all -- the CSP is
  `script-src 'none'` -- so the loop is keyframes and `animation-delay`, and
  the countdown digits are a strip of numbers slid one line at a time.
*/
.screens {
  position: relative;
  margin-top: auto;
  min-height: 208px;
}
.scr {
  position: absolute;
  inset: auto 0 0 0;
  opacity: 0;
}
.scr-1 { animation: scr 12s var(--ease) infinite 0s; }
.scr-2 { animation: scr 12s var(--ease) infinite 3s; }
.scr-3 { animation: scr 12s var(--ease) infinite 6s; }
.scr-4 { animation: scr 12s var(--ease) infinite 9s; }

@keyframes scr {
  0%   { opacity: 0; transform: translateY(10px); }
  4%   { opacity: 1; transform: none; }
  22%  { opacity: 1; transform: none; }
  26%  { opacity: 0; transform: translateY(-6px); }
  100% { opacity: 0; transform: translateY(10px); }
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.13);
  font: 500 13px/1 var(--sans);
  color: rgba(255, 255, 255, 0.8);
}

.card {
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 22px;
  padding: 15px 16px 16px;
  backdrop-filter: blur(8px);
}
.card b {
  display: block;
  font: 600 16px/1.3 var(--sans);
  margin-bottom: 4px;
}
.card p { font: 400 13px/1.45 var(--sans); color: rgba(255, 255, 255, 0.62); }
.card .card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 600 11px/1 var(--sans);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--night-alert);
  margin-bottom: 12px;
}
.card .card-foot { margin-top: 12px; font-size: 12px; }
.dot.alert { background: var(--night-alert); }

/* The countdown. The ring empties and the number falls with it. */
.ring-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 13px;
}
.ring { width: 46px; height: 46px; flex: 0 0 auto; transform: rotate(-90deg); }
.ring-track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.16);
  stroke-width: 4;
}
.ring-sweep {
  fill: none;
  stroke: var(--night-alert);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 150.8;
  stroke-dashoffset: 150.8;
}
.count {
  display: block;
  height: 30px;
  overflow: hidden;
  font: 300 30px/30px var(--display);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.count b { display: block; height: 30px; margin: 0; font: inherit; }

.btn-light {
  margin-top: 13px;
  height: 40px;
  border-radius: 12px;
  background: #F7F7F5;
  color: #111110;
  display: grid;
  place-items: center;
  font: 600 14px/1 var(--sans);
}

/* Who is coming. Rows land one after another, the way answers arrive. */
.who {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  font: 500 14px/1 var(--sans);
}
.who em {
  margin-left: auto;
  font: 400 12px/1 var(--sans);
  font-style: normal;
  color: rgba(255, 255, 255, 0.45);
}
.who em.ok { color: var(--night-jade); }
.av {
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.13);
  display: grid;
  place-items: center;
  font: 600 11px/1 var(--sans);
  color: rgba(255, 255, 255, 0.75);
}

/* Less dead glass when the phone is stacked under the steps. */
@media (max-width: 620px) {
  .phone { aspect-ratio: 9 / 14; padding-top: 22px; }
  .phone-clock { font-size: 52px; margin-top: 4px; }
  .screens { min-height: 196px; }
}

@media (prefers-reduced-motion: no-preference) {
  .ring-sweep { animation: sweep 12s linear infinite 3s; }
  .count b { animation: tick 12s steps(1, end) infinite 3s; }
  .who-1 { animation: land 12s var(--ease) infinite 6s; }
  .who-2 { animation: land 12s var(--ease) infinite 6.25s; }
  .who-3 { animation: land 12s var(--ease) infinite 6.5s; }

  /* The step list runs off the same clock as the phone. */
  .steps > li { color: inherit; animation: lit 12s var(--ease) infinite; }
  .steps > li:nth-child(1) { animation-delay: 0s; }
  .steps > li:nth-child(2) { animation-delay: 3s; }
  .steps > li:nth-child(3) { animation-delay: 6s; }
  .steps > li:nth-child(4) { animation-delay: 9s; }
}

@keyframes sweep {
  0%   { stroke-dashoffset: 0; }
  25%  { stroke-dashoffset: 150.8; }
  100% { stroke-dashoffset: 150.8; }
}
/*
  Seven stops inside the first quarter of the loop: 30, 25, 20, 15, 10, 5, 0.
  The strip slides one 30px line at a time, which is the only way to count in
  CSS without a script.
*/
@keyframes tick {
  0%,     3.5%  { transform: translateY(0); }
  3.6%,   7.1%  { transform: translateY(-30px); }
  7.2%,  10.7%  { transform: translateY(-60px); }
  10.8%, 14.2%  { transform: translateY(-90px); }
  14.3%, 17.8%  { transform: translateY(-120px); }
  17.9%, 21.4%  { transform: translateY(-150px); }
  21.5%, 100%   { transform: translateY(-180px); }
}
@keyframes land {
  0%   { opacity: 0; transform: translateY(6px); }
  5%   { opacity: 1; transform: none; }
  22%  { opacity: 1; transform: none; }
  26%, 100% { opacity: 0; transform: none; }
}
@keyframes lit {
  0%, 26%, 100% { opacity: 0.45; }
  3%, 23%       { opacity: 1; }
}

/* Reduced motion gets the decisive frame rather than a blank phone. */
@media (prefers-reduced-motion: reduce) {
  .scr { position: relative; opacity: 0; }
  .scr-2 { opacity: 1; }
  .scr-1, .scr-3, .scr-4 { display: none; }
  .count b { transform: translateY(0); }
  .ring-sweep { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: no-preference) {
  /* The app's BreatheDot, at the app's 1600ms. */
  .breathe { animation: breathe 1.6s ease-in-out infinite; }
}
@keyframes breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* --------------------------------------------------------- veto chips */

/*
  Three specimens at one scale, so the rule reads off the page instead of out
  of a paragraph: two ordinary things that shake in the same band, and the one
  that slows down while it does it.
*/
.vetoes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
  gap: 20px;
  margin-top: clamp(32px, 5vw, 48px);
}
.veto {
  border: 1px solid var(--hair-firm);
  border-radius: 16px;
  padding: 18px 20px 16px;
  background: var(--card);
}
.veto-name { font: 600 15.5px/1.3 var(--sans); color: var(--ink); }
.veto svg { display: block; width: 100%; height: auto; margin: 14px 0 12px; }
.veto-line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.veto-rate { font: 500 12px/1 var(--mono); color: var(--faint); }
.veto-verdict {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--hair);
  font: 600 13px/1 var(--sans);
  color: var(--faint);
}
.veto.is-out { background: transparent; }
.veto.is-out .veto-line { stroke: var(--faint); stroke-width: 1.3; }
.veto.is-hit { border-color: var(--hair-strong); }
.veto.is-hit .veto-verdict { color: var(--ink); }

/* Which types have a signature at all, and which simply do not. */
.types {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 22px 0 20px;
}
.type {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  font: 500 13.5px/1 var(--sans);
  color: var(--faint);
}
.type span { font: 500 11.5px/1 var(--mono); color: var(--faint); }
.type.is-seen {
  border-color: var(--hair-strong);
  color: var(--ink);
}

/* ------------------------------------------------------- platform notes */

.notes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 26px 48px;
  margin-top: 40px;
}
.notes > li {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 16px;
}
.notes p { font-size: 15px; color: var(--muted); max-width: 46ch; }
.notes strong { color: var(--ink); }

/* --------------------------------------------------- what it is allowed to say */

/*
  The one distinction the whole regulatory posture turns on, shown as the two
  notifications rather than argued in a paragraph. The second one is struck
  through because it is the thing the app is never allowed to send.
*/
.says {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 20px;
  margin-top: 30px;
}
.say-tag {
  font: 600 11.5px/1.1 var(--sans);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}
.notif {
  border: 1px solid var(--hair-firm);
  border-radius: 18px;
  padding: 14px 16px 15px;
  background: var(--card);
}
.notif-app {
  display: flex;
  align-items: center;
  gap: 7px;
  font: 600 10.5px/1 var(--sans);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 9px;
}
.notif .dot { width: 7px; height: 7px; background: var(--alert); }
.notif b {
  display: block;
  font: 600 16px/1.3 var(--sans);
  color: var(--ink);
  margin-bottom: 4px;
}
.notif p { font-size: 13px; line-height: 1.45; color: var(--muted); }
.say.is-no .notif { background: transparent; border-style: dashed; }
.say.is-no .notif b {
  color: var(--faint);
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
}
.say.is-no .notif-app { opacity: 0.5; }

/* ----------------------------------------------------------------- table */

.table-scroll { overflow-x: auto; margin-top: 34px; }

table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: 14.5px;
}
th, td {
  text-align: left;
  padding: 15px 18px 15px 0;
  border-bottom: 1px solid var(--hair);
  vertical-align: top;
}
thead th {
  font: 600 11.5px/1.1 var(--sans);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 12px;
}
tbody th {
  font: 600 15px/1.4 var(--sans);
  color: var(--ink);
  white-space: nowrap;
}
td { color: var(--muted); }
/*
  Deliberately not jade. Three green ticks in one table would spend the whole
  jade budget the design system sets (at most two per screen, and it is the
  mark and the live dot that need it). Weight and value carry the column on
  their own, which is also the house rule: the primary is ink, not a colour.
*/
td.yes { color: var(--ink); font-weight: 600; }
td.no { color: var(--faint); }

/* ---------------------------------------------------------------- footer */

.site-footer {
  border-top: 1px solid var(--hair);
  padding: 44px 0 56px;
  font-size: 13.5px;
  color: var(--faint);
}
.footer-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 32px;
  align-items: baseline;
  justify-content: space-between;
}
.footer-note { max-width: 52ch; line-height: 1.55; }
.site-footer a { color: var(--muted); }

/*
  Cascade order is load-bearing here: this block must sit AFTER the base
  `table` rules. At equal specificity the later rule wins, so placed earlier
  the `min-width: 560px` above survived, and the stacked layout rendered 560px
  wide inside a 320px screen with every value off the right edge.

  Below the table's natural width the four columns stop fitting, and a
  horizontally-scrolling table hides its last column with no hint it is there.
  Overnight cover and heart rate are the two answers a visitor came for, so
  each device becomes its own block with the column names carried down as
  labels. `data-label` on every cell is what makes that work without a second
  copy of the markup.
*/
@media (max-width: 640px) {
  .table-scroll { overflow-x: visible; }
  /*
    Every box goes block. Leaving `table` as `display: table` while the rows
    are blocks makes the engine generate anonymous table boxes around the
    cells, and the values disappear into them.
  */
  table, tbody, tbody tr, tbody th, tbody td { display: block; }
  table { min-width: 0; }
  thead { display: none; }
  tbody tr {
    display: block;
    padding: 16px 0 6px;
    border-bottom: 1px solid var(--hair);
  }
  tbody th {
    display: block;
    padding: 0 0 10px;
    border: 0;
    font-size: 16px;
  }
  tbody td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 20px;
    padding: 7px 0;
    border: 0;
  }
  tbody td::before {
    content: attr(data-label);
    color: var(--faint);
    font-weight: 400;
  }
}
