/* OneNect marketing site
   Follows www/ART-DIRECTION.md exactly. Read that first.

   Two rules this file must never break:
   1. No gradient of any kind. Not one. Flat fills only.
   2. White ground. Product colour arrives as a solid fill, never as a wash.

   Rewritten 2026-09-03 for the direction in
   docs/superpowers/specs/2026-09-03-www-the-circle-closes-design.md: the ring
   draws as the refusals strike, the phones stand on an ink shelf, and the
   whole site, phones included, has a dark theme from packages/brand. */

/* ============================================================ tokens */

:root {
  color-scheme: light;

  /* ground and ink */
  --paper: #ffffff;
  --card: #ffffff;
  --ink: #0b1112;      /* 19.0:1 on white */
  --ink-2: #55636b;    /* 6.21:1 */
  --ink-3: #626f77;    /* 5.17:1 on white, 4.59:1 on --rule-2, 4.81:1 on --shade */
  --rule: #e3e8ea;     /* separators only: 1.24:1, never the sole boundary of a control */
  --rule-strong: #86959b; /* 3.09:1, for a boundary that has to be seen */
  --rule-2: #eef2f3;
  --shade: #f4f7f8;

  /* The refused nouns in the creed. Grey enough to read as taken out, dark
     enough to read: 4.6:1 on white. */
  --refused: #6b7a73;

  /* The shelf the four phones stand on: the one plate of ink on the light
     site. The phones on it wear the brand's dark surfaces. */
  --shelf: #0b1112;
  --on-shelf: #f3f4f6;
  --on-shelf-2: #cdd0d5;
  --on-shelf-3: #9ea1a7;
  --shelf-rule: #2a2c30;

  /* A phone's body. Ink on paper, so it reads as a device rather than a
     wireframe; on the shelf and in the dark it takes the brand's card grey. */
  --bezel: #0b1112;
  --bezel-edge: #26282c;

  /* The four plates, from packages/brand/src/mark.ts. www/check-glyphs.mjs
     fails if any of them drifts from it, and it checks this file by name,
     because this file was one of the three that went on shipping the retired
     values after the colours moved. All four take WHITE on the plate.

     --<k>-ink is the colour that carries TEXT and marks on the page ground: the
     plate on white, the brand's `bright` on black. --on-<k> is what sits on
     the plate itself. Both flip with the theme below. */
  --corp: #0d6e6e;   --corp-soft: #d3edf3;   --corp-ink: #0d6e6e;   --on-corp: #ffffff;
  --faith: #067497;  --faith-soft: #dcf1fb;  --faith-ink: #067497;  --on-faith: #ffffff;
  --social: #1c5b34; --social-soft: #e2f2e5; --social-ink: #1c5b34; --on-social: #ffffff;
  --vip: #003757;    --vip-soft: #dce8f5;    --vip-ink: #003757;    --on-vip: #ffffff;

  /* The product on a dark ground WHATEVER the theme: the brand's `bright`,
     verbatim. The shelf is ink on the light site, and the captions on it were
     being set in --<k>-ink, which is the plate until the page goes dark: Estate
     was #003757 on #0b1112, 1.53:1, and nobody could read its name. These do
     not flip; in the dark --<k>-ink already equals them. */
  --corp-bright: #2dd4bf; --faith-bright: #7fd7fd; --social-bright: #a5e5b7; --vip-bright: #6fa8dc;

  /* The neutral mark's node: packages/brand MARK_NODE_INK, a near-black outside
     the four so the centre reads as a node and not a fifth colour. White in the
     dark, which is MARK_NODE_INK_ON_DARK. check-ring.mjs holds both to
     ringFrame('closed', ground). It used to be --ink, which is close and is
     not the same decision. */
  --node: #0f1a1d;

  /* Literals on purpose, held as tokens so the purpose is visible: a verdict is
     not a product hue and an alert is the same colour in the dark, so none of
     these flip. White on each is measured by check-theme.mjs. */
  --alert: #b3261e;  --on-alert: #ffffff;
  --amber: #a1440a;  --on-amber: #ffffff;
  --sos: #8f1d16;    --on-sos: #ffffff;
  /* A camera lens is black in both themes. */
  --lens: #0b1112;   --on-lens: #ffffff;
  /* The three verdicts on a scan. Status fills, so they DO take the brand's
     dark fills in the dark: the light values are 2.7:1 on the dark card. */
  --verdict-ok: #0a6e3d; --verdict-no: #b3261e; --verdict-mid: #b06f00;
  /* A phone standing on the shelf wears the brand's card grey whatever the
     theme, because the shelf is that ground on both. */
  --bezel-on-shelf: #26282c; --bezel-on-shelf-edge: #3a3d43;

  /* the live world. The page ships with these set in a per-page style block;
     a tab change rewrites them and everything downstream follows on one beat.
     They point at the product tokens rather than repeating a hex, so the theme
     can move the product and the world follows. */
  --hue: var(--corp-plate);
  --hue-soft: var(--corp-soft);
  --on-hue: var(--on-corp);
  --hue-ink: var(--corp-ink);

  --display: "Familjen Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --body: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "Martian Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --beat: 420ms;
  --ease: cubic-bezier(.22, 1, .36, 1);
  --draw: cubic-bezier(.22, .61, .36, 1);

  /* One measure for the whole page. The hero used to be capped at 1560px and
     every other section at 1320px, so above 1320px the hero and everything
     under it sat on two different left edges: 72px and 132px at 1440. On a
     page whose whole layout argument is a single hard left edge, that is the
     one measurement that has to be exact. */
  --measure: 1320px;
  --gut: clamp(20px, 5vw, 72px);
  --bar-h: 64px;
}

/* ── The dark theme ──────────────────────────────────────────────────────────
 *
 * Every value is packages/brand/src/index.ts `darkColors` or
 * `productMark[k].bright`, which is the set the brand defines for arcs on a
 * dark ground. The page ground is true black because the brand's is, and the
 * card surface stays one step above it so a lifted surface still lifts.
 *
 * The four dark soft surfaces are the site's own derivation, because
 * packages/brand carries a soft tint for the light ground only: each is its
 * plate taken down over the card, and every text pairing on them is measured.
 * --<k>-ink on its own dark soft: Corp 7.51, Faith 9.16, OneNect 10.68,
 * Estate 6.40. --ink-2 on the worst of them: 9.04. --ink-3 on it: 5.40.
 *
 * The brights are light colours, so what sits ON a plate flips to ink: the
 * darkest of the four brights carries #0b1112 at 7.53:1.
 *
 * --rule-strong is the second site derivation. It is "a boundary that has to
 * be seen", and the brand's dark gray300 (#4a4d53) is 2.48:1 on black and
 * 2.09:1 on the card, so a quiet button's border and the empty matrix dot were
 * under the 3:1 floor in the dark. This is the lightest neutral that clears it
 * on both: 3.93:1 on the page, 3.33:1 on the card. --node is the brand's
 * MARK_NODE_INK_ON_DARK and the verdict dots are its dark status fills.
 *
 * The block is written twice because a custom property cannot be reused as a
 * rule: once for a system preference the page has not overridden, once for
 * the toggle. Change one and change the other; check-glyphs.mjs fails if they
 * differ, and check-theme.mjs measures every pair on both grounds. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper: #000000; --card: #17181b;
    --ink: #f3f4f6; --ink-2: #cdd0d5; --ink-3: #9ea1a7;
    --rule: #2a2c30; --rule-strong: #686b72; --rule-2: #1f2125; --shade: #17181b;
    --refused: #7d8a84;
    --shelf: #17181b; --shelf-rule: #33363c;
    --bezel: #26282c; --bezel-edge: #3a3d43;
    --node: #ffffff;
    --verdict-ok: #3dbe7e; --verdict-no: #f0554a; --verdict-mid: #f5b94b;
    --corp-soft: #10312f;   --corp-ink: #2dd4bf;   --on-corp: #0b1112;
    --faith-soft: #0d2b3a;  --faith-ink: #7fd7fd;  --on-faith: #0b1112;
    --social-soft: #11291b; --social-ink: #a5e5b7; --on-social: #0b1112;
    --vip-soft: #0c2236;    --vip-ink: #6fa8dc;    --on-vip: #0b1112;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: #000000; --card: #17181b;
  --ink: #f3f4f6; --ink-2: #cdd0d5; --ink-3: #9ea1a7;
  --rule: #2a2c30; --rule-strong: #686b72; --rule-2: #1f2125; --shade: #17181b;
  --refused: #7d8a84;
  --shelf: #17181b; --shelf-rule: #33363c;
  --bezel: #26282c; --bezel-edge: #3a3d43;
  --node: #ffffff;
  --verdict-ok: #3dbe7e; --verdict-no: #f0554a; --verdict-mid: #f5b94b;
  --corp-soft: #10312f;   --corp-ink: #2dd4bf;   --on-corp: #0b1112;
  --faith-soft: #0d2b3a;  --faith-ink: #7fd7fd;  --on-faith: #0b1112;
  --social-soft: #11291b; --social-ink: #a5e5b7; --on-social: #0b1112;
  --vip-soft: #0c2236;    --vip-ink: #6fa8dc;    --on-vip: #0b1112;
}
/* In the dark the plate itself is too dark to sit on black as a fill, so
   wherever a plate is a FILL on the page ground it takes the bright. The
   soft surfaces and what sits on a plate are handled by the tokens above. */
:root { --corp-plate: var(--corp); --faith-plate: var(--faith); --social-plate: var(--social); --vip-plate: var(--vip); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --corp-plate: var(--corp-ink); --faith-plate: var(--faith-ink); --social-plate: var(--social-ink); --vip-plate: var(--vip-ink); }
}
:root[data-theme="dark"] { --corp-plate: var(--corp-ink); --faith-plate: var(--faith-ink); --social-plate: var(--social-ink); --vip-plate: var(--vip-ink); }

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--bar-h) + 24px);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.55;
  overflow-x: hidden;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  transition: color var(--beat) var(--ease), background-color var(--beat) var(--ease);
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -.035em;
  line-height: .98;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
dl, dd { margin: 0; }

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

::selection { background: var(--hue); color: var(--on-hue); }

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

.skip {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--ink); color: var(--paper); padding: 10px 16px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; text-decoration: none;
  transition: top 160ms var(--ease);
}
.skip:focus { top: 12px; }

main:focus { outline: none; }

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

/* ============================================================ type roles */

.eyebrow {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-2); margin: 0;
}

.lede {
  font-size: clamp(17px, 1.3vw, 19px);
  color: var(--ink-2);
  max-width: 52ch;
  margin-top: 22px;
}

.h-sec { font-size: clamp(34px, 4.6vw, 64px); letter-spacing: -.04em; margin-top: 16px; }

.h-sub {
  font-family: var(--display); font-size: clamp(20px, 2vw, 26px); font-weight: 600;
  letter-spacing: -.03em; line-height: 1.12; margin: 0;
}

/* the long notes are file paths, sources and caveats. Uppercase mono is right
   for a three word label and wrong for a sentence, so these are sentence case. */
.note-long {
  font-family: var(--mono); font-size: 11px; line-height: 1.6;
  letter-spacing: -.01em; color: var(--ink-3); margin-top: 16px; max-width: 62ch;
}
.note-long a { color: var(--ink-2); }

/* Every section-level rule that sets vertical padding on a .shell element must
   use padding-block, never the `padding: <y> 0` shorthand. Seven of them used
   the shorthand, which reset this gutter to zero, and the page ran flush to the
   viewport edge at every width below 1320px. It was invisible above 1320px,
   where the max-width auto margin supplies an inset of its own, which is why it
   survived review at 1440. */
.shell { max-width: var(--measure); margin: 0 auto; padding-left: var(--gut); padding-right: var(--gut); }
.rule-top { border-top: 1px solid var(--rule); }

/* ============================================================ the tab bar
   The signature. Three flat colour tabs, full bleed, the active one physically
   joined to the page below it. A platform of a base and its pillars is a filing
   system, so the site is filed. These are real links to real pages: the
   transition is an enhancement, not the mechanism. */

.bar {
  position: sticky; top: 0; z-index: 80;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  display: grid; grid-template-columns: auto 1fr auto;
  align-items: stretch; min-height: var(--bar-h);
  transition: background-color var(--beat) var(--ease);
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 0 clamp(14px, 2.2vw, 24px);
  text-decoration: none; border-right: 1px solid var(--rule); flex: none;
}
.brand-mark { width: 30px; height: 30px; display: block; flex: none; }
.brand-name { font-family: var(--display); font-weight: 700; font-size: 19px; letter-spacing: -.045em; }
.brand[aria-current="page"] .brand-name { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 5px; }

.worlds { display: grid; grid-template-columns: repeat(var(--tab-n, 3), 1fr); min-width: 0; }

.world-tab {
  position: relative;
  border-right: 1px solid var(--rule);
  background: var(--paper); color: var(--ink-2);
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 0 6px; min-width: 0;
  transition: background 220ms var(--ease), color 220ms var(--ease);
}
.world-tab:last-child { border-right: 0; }
.world-tab:hover { background: var(--rule-2); color: var(--ink); }

.world-tab .disc {
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: var(--tab-plate); color: var(--tab-on);
  transition: transform 260ms var(--ease);
}
.world-tab:hover .disc { transform: scale(1.09); }
.world-tab .disc svg { width: 14px; height: 14px; display: block; }

.world-tab[aria-current="page"] { background: var(--tab-plate); color: var(--tab-on); }
.world-tab[aria-current="page"] .disc { background: var(--tab-on); color: var(--tab-plate); }

/* The ring is drawn INSIDE the tab. The global :focus-visible offsets it 3px
   outward, which on a tab put the ring and its gap on the NEXT tab, which
   paints over it. Inside the tab it is complete, nothing can paint over it, and
   it takes the one colour guaranteed to read on that tab's own background. */
.world-tab:focus-visible {
  outline-offset: -6px;
  background: var(--rule-2); color: var(--ink);
}
.world-tab[aria-current="page"]:focus-visible {
  outline-color: var(--tab-on);
  background: var(--tab-plate); color: var(--tab-on);
}
.world-tab:focus-visible .disc { transform: scale(1.09); }

.tab-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Above 860px the three tabs are as wide as their labels and the rest of the
   bar is shelf. At 860 and below they go back to equal columns, where each tab
   stacks its glyph over its label and the wordmark is dropped. */
@media (min-width: 861px) {
  .worlds { grid-template-columns: repeat(var(--tab-n, 3), auto) minmax(0, 1fr); }
  .world-tab { padding: 0 clamp(20px, 3vw, 40px); }
  .world-tab:last-child { border-right: 1px solid var(--rule); }
}

/* ── The theme switch ────────────────────────────────────────────────────────
 *
 * One control, at the end of the bar. Its disc is the mark's node: hollow on
 * the light ground, filled when the page is dark. Pressing it flips the page
 * and every phone on it on the same beat, which is the plainest proof on the
 * site that the screens are live markup and not pictures. */
.theme {
  border: 0; border-left: 1px solid var(--rule); background: var(--paper); color: var(--ink-2);
  font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  display: flex; align-items: center; gap: 9px; padding: 0 clamp(14px, 2vw, 24px); cursor: pointer;
  transition: background 220ms var(--ease), color 220ms var(--ease);
}
.theme:hover { background: var(--rule-2); color: var(--ink); }
.theme:focus-visible { outline-offset: -6px; }
.theme-disc {
  width: 14px; height: 14px; border-radius: 50%; flex: none;
  border: 2px solid currentColor; background: transparent;
  transition: background 220ms var(--ease);
}
.theme[aria-pressed="true"] .theme-disc { background: currentColor; }
html:not(.js) .theme { display: none; }

/* ============================================================ hero */

.hero {
  display: grid;
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
  padding-top: clamp(38px, 5.5vw, 82px);
  padding-bottom: clamp(34px, 4.5vw, 68px);
  max-width: var(--measure); margin: 0 auto;
  padding-left: var(--gut);
}
/* The home hero is two columns: the refusals and the ring they draw. The four
   phones get the full width on the shelf under it. */
.hero-home {
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 480px);
  gap: clamp(24px, 4vw, 72px); padding-right: var(--gut);
  padding-bottom: clamp(40px, 5vw, 80px);
}
.hero-home .lede { max-width: 58ch; }
/* One column. The big ring used to sit beside the words on all three pillar
   pages, which made it the one element that was identical on the three pages
   whose whole job is not to feel like each other. It is gone from the pillar
   hero and on the home page, where the ring is the argument. */
.hero-product { grid-template-columns: minmax(0, 1fr); padding-right: var(--gut); }
.hero-product .hero-words { max-width: 66rem; }
.hero-product .lede { max-width: 60ch; }
.hero-note { margin-top: 18px; max-width: 62ch; }

.hero-words { min-width: 0; }

.hero h1 {
  font-size: clamp(38px, 4.9vw, 72px);
  letter-spacing: -.045em; line-height: .96; margin: 18px 0 0;
}

/* the swapping noun: clipped to its own line box, out up, in from below */
.swap { display: inline-block; position: relative; overflow: hidden; vertical-align: bottom; color: var(--hue-ink); }
.swap-in { display: inline-block; transform: translateY(0); opacity: 1; transition: transform 380ms var(--ease), opacity 260ms linear; }
.swap.in .swap-in { transform: translateY(.9em); opacity: 0; transition: none; }

.hero-act { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; align-items: center; }

.btn {
  border: 0; cursor: pointer;
  background: var(--ink); color: var(--paper);
  font-family: var(--body); font-size: 15px; font-weight: 500;
  padding: 13px 22px; border-radius: 2px;
  text-decoration: none; display: inline-flex; align-items: center; gap: 9px;
  transition: background 200ms var(--ease), color 200ms var(--ease);
}
.btn:hover { background: var(--hue); color: var(--on-hue); }
.btn svg { width: 15px; height: 15px; }

.btn-quiet { background: transparent; color: var(--ink); border: 1px solid var(--rule-strong); padding: 12px 20px; }
.btn-quiet:hover { background: transparent; border-color: var(--ink); color: var(--ink); }

/* ── The creed ──────────────────────────────────────────────────────────────
 *
 * The home page's thesis, and the one place on this site that raises its voice.
 *
 * Every competitor sells reach: more people, more feed, more of everything. The
 * only claim OneNect can make that none of them can is a list of things it
 * refuses to do, and the product enforces all four; the note above `homeMain()`
 * in www/build.mjs carries that argument. So the hero is that list, and the
 * rule struck through each noun is the design carrying the argument rather than
 * decorating it: these are the things that have been taken out.
 *
 * The strike is drawn rather than typed. `text-decoration: line-through` cannot
 * be animated, sits at a weight the browser chooses, and would read as deleted
 * text to a screen reader, which is the wrong meaning. This is a pseudo-element
 * ruled across the noun, so its weight, colour and timing are ours, and the
 * words stay ordinary text to anything that is not looking at them.
 *
 * ── The sequence ────────────────────────────────────────────────────────────
 *
 * One timeline, once per page load, and everything in the hero is on it:
 *
 *   .00  eyebrow
 *   .16  refusal one rises in;      .30 its strike draws and the ring's first
 *                                       quarter draws with it, .42s each
 *   .46  refusal two;               .60 strike, quarter two
 *   .76  refusal three;             .90 strike, quarter three
 *  1.06  refusal four;             1.20 strike, quarter four: the circle closes
 *  1.55  the node lands in the centre and the turn line goes solid: what is left
 *  1.75  the four plates cross-fade over the ink ring
 *  1.85  the lede;                 1.95 the actions
 *
 * The ring is one boundary drawn by four refusals, and the colours arrive
 * after, which is the argument in the right order. A quarter is NOT tied to a
 * refusal in meaning: four products and four refusals is a coincidence.
 *
 * With motion reduced everything is in its final state: struck, closed,
 * coloured, and nothing fades. The meaning is in the end state, so it arrives
 * at once rather than being removed along with the motion. */
.creed {
  list-style: none;
  margin: clamp(18px, 2.4vw, 30px) 0 clamp(22px, 3vw, 36px);
  padding: 0;
  display: grid;
  gap: clamp(8px, 1.1vw, 16px);
}
.creed li {
  display: flex;
  align-items: baseline;
  gap: clamp(10px, 1.4vw, 20px);
  font-family: var(--display);
  font-size: clamp(32px, 5.3vw, 74px);
  line-height: 1.0;
  letter-spacing: -.04em;
  opacity: 0; transform: translate3d(0, .3em, 0);
  animation: rise .5s var(--ease) forwards;
}
.creed li:nth-child(1) { animation-delay: .16s; }
.creed li:nth-child(2) { animation-delay: .46s; }
.creed li:nth-child(3) { animation-delay: .76s; }
.creed li:nth-child(4) { animation-delay: 1.06s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* "No" is the constant, so it recedes: the eye should travel the nouns. */
.creed-no {
  color: var(--ink-3);
  font-weight: 500;
  font-size: .46em;
  letter-spacing: -.01em;
  flex: none;
  /* Optical alignment. The lowercase nouns sit on the baseline; without this
     the small "No" floats and the column reads ragged. */
  transform: translateY(-.06em);
}
.creed-thing {
  /* The refused things recede and the rule reads as green against them. What
     remains, in the line below, is the only solid ink in the hero. That is the
     hierarchy carrying the argument: these are gone, this is what is left. */
  color: var(--refused);
  font-weight: 700;
  position: relative;
}
/* Where the rule sits: measured on the rendered page rather than set by eye.
   At 68px Familjen Grotesk Bold puts the x-height midpoint at .640em and the
   ink centre of a whole lowercase word at .662em; a .1em rule with its top at
   .60em has its centre at .650em, between them, at every width. .1em is about
   two thirds of the stem weight, which is what makes it read as a mark of the
   same hand. All of this is tied to `line-height: 1.0` on `.creed li`: change
   that and re-measure rather than nudging this. */
.creed-thing::after {
  content: "";
  position: absolute;
  left: -.04em;
  right: -.04em;
  top: .60em;
  height: .1em;
  background: var(--social-ink);
  border-radius: .03em;
  transform: scaleX(0);
  transform-origin: left center;
  animation: creed-strike .42s var(--draw) forwards;
}
.creed li:nth-child(1) .creed-thing::after { animation-delay: .30s; }
.creed li:nth-child(2) .creed-thing::after { animation-delay: .60s; }
.creed li:nth-child(3) .creed-thing::after { animation-delay: .90s; }
.creed li:nth-child(4) .creed-thing::after { animation-delay: 1.20s; }
@keyframes creed-strike { to { transform: scaleX(1); } }

/* The turn. The refusals are the argument; this is what they leave behind, so
   it is set quieter than them on purpose and carries the h1. It starts grey
   and goes solid the moment the circle closes. */
h1.creed-turn {
  font-size: clamp(24px, 3vw, 40px);
  line-height: 1.18;
  letter-spacing: -.025em;
  font-weight: 600;
  max-width: 22ch;
  margin: 0;
  color: var(--ink-3);
  animation: turn .6s var(--ease) 1.55s forwards;
}
@keyframes turn { to { color: var(--ink); } }
.hero-home .lede { margin-top: 14px; opacity: 0; animation: rise .5s var(--ease) 1.85s forwards; }
.hero-home .hero-act { opacity: 0; animation: rise .5s var(--ease) 1.95s forwards; }
.hero-home .eyebrow { opacity: 0; animation: rise .5s var(--ease) 0s forwards; }

/* ── The ring ────────────────────────────────────────────────────────────────
 *
 * The brand mark, drawn. Two layers of the same four quarter arcs from
 * packages/brand: an ink layer that draws itself a quarter at a time, one
 * quarter per strike, and a coloured layer that cross-fades over it once the
 * circle is closed. The node is the neutral mark's node, not a glyph disc: the
 * home page carries no one product.
 *
 * `pathLength="1"` on every path makes the dash arithmetic unit-free. The
 * offset starts at 1.02 rather than 1 because a zero-length dash with a round
 * cap still renders as a dot in Chromium. */
.hero-ring { width: min(44vw, 480px); aspect-ratio: 1; justify-self: end; }
.hero-ring svg { width: 100%; height: 100%; display: block; overflow: visible; }
.ring-ink path {
  fill: none; stroke: var(--ink); stroke-linecap: round;
  stroke-dasharray: 1 2; stroke-dashoffset: 1.02;
  animation: ring-draw .42s var(--draw) forwards;
}
.ring-ink path:nth-child(1) { animation-delay: .30s; }
.ring-ink path:nth-child(2) { animation-delay: .60s; }
.ring-ink path:nth-child(3) { animation-delay: .90s; }
.ring-ink path:nth-child(4) { animation-delay: 1.20s; }
@keyframes ring-draw { to { stroke-dashoffset: 0; } }
.ring-hue path { fill: none; stroke-linecap: round; }
.ring-hue { opacity: 0; animation: fade .6s linear 1.75s forwards; }
@keyframes fade { to { opacity: 1; } }
.ring-node {
  fill: var(--node);
  transform: scale(0); transform-origin: 60px 60px;
  animation: node .5s var(--ease) 1.55s forwards;
}
@keyframes node { to { transform: scale(1); } }

/* ============================================================ the shelf
   The four phones, on an ink plate, edge to edge. It is the one plate of
   contrast on the light site, and the reason is specific: the brand defines a
   `bright` for every product for arcs on a dark ground, and this is that
   ground. The phones enter with a short stagger as the shelf scrolls into
   view and the poll bars inside them fill from zero, which is the app doing
   what it does. No JavaScript is involved in any of it. */

.shelf { background: var(--shelf); color: var(--on-shelf); transition: background-color var(--beat) var(--ease); }
.shelf .shell { padding-top: clamp(26px, 3.4vw, 52px); padding-bottom: clamp(26px, 3.4vw, 52px); }
.shelf-head { display: flex; justify-content: space-between; align-items: baseline; gap: 20px; flex-wrap: wrap; }
.shelf-head .eyebrow { color: var(--on-shelf-3); }
.shelf-head .note-long { margin-top: 0; color: var(--on-shelf-3); }

.strip { display: flex; gap: clamp(14px, 2vw, 34px); align-items: flex-start; padding-top: clamp(18px, 2.4vw, 34px); }
.strip-item {
  flex: 1 1 0; min-width: 0; margin: 0;
  transform: translate3d(var(--tilt, 0px), 0, 0);
  transition: transform 500ms var(--ease);
}
.strip-item:nth-child(2n) { margin-top: 26px; }

.strip-link { text-decoration: none; display: block; color: inherit; }
.strip-dev { display: block; }
.strip-dev .device { --bezel: var(--bezel-on-shelf); --bezel-edge: var(--bezel-on-shelf-edge); margin: 0 auto; }
.strip-link .device { transition: transform 300ms var(--ease); }
.strip-link:hover .device,
.strip-link:focus-visible .device { transform: translateY(-6px); }

.strip-cap { display: flex; flex-direction: column; gap: 3px; margin-top: 16px; padding-left: 2px; }
.strip-name { font-family: var(--display); font-size: 17px; font-weight: 700; letter-spacing: -.035em; color: var(--bright); }
.strip-what { font-size: 12.5px; color: var(--on-shelf-2); }
.strip-status {
  font-family: var(--mono); font-size: 9px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--on-shelf-3); margin-top: 2px;
}
.strip-status[data-built="1"] { color: var(--on-shelf); }

/* Scroll-driven entrances, where the browser has them. Where it does not, the
   phones are simply there, which is also what a crawler and a printer get. */
@supports (animation-timeline: view()) {
  @media (min-width: 861px) {
    .strip-item {
      animation: shelf-in linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 55%;
    }
    .strip-item:nth-child(2) { animation-range: entry 12% entry 62%; }
    .strip-item:nth-child(3) { animation-range: entry 19% entry 69%; }
    .strip-item:nth-child(4) { animation-range: entry 26% entry 76%; }
    /* view() binds to the nearest scroll container, and a bar sits inside
       three boxes with overflow hidden, so its own view() was already finished
       before the page had scrolled. The phone names a timeline and the bar
       follows it. */
    .strip-dev { view-timeline-name: --phone; }
    .shelf .w-poll .opt .tr i {
      transform-origin: left center;
      animation: bar-fill linear both;
      animation-timeline: --phone;
      animation-range: entry 40% entry 100%;
    }
  }
}
@keyframes shelf-in { from { opacity: 0; transform: translate3d(var(--tilt, 0px), 28px, 0); } }
@keyframes bar-fill { from { transform: scaleX(0); } }

/* ============================================================ status band
   A flat field of the product's own soft surface, edge to edge. It is the one
   thing on a product page a visitor should not be able to scroll past without
   reading, so it gets the colour rather than the decoration. */

.status-band { background: var(--hue-soft); transition: background var(--beat) var(--ease); }

.status {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(16px, 3vw, 40px); align-items: center;
  padding-top: clamp(18px, 2vw, 26px); padding-bottom: clamp(18px, 2vw, 26px);
}
.status-tag {
  font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; white-space: nowrap;
  background: var(--hue); color: var(--on-hue); padding: 7px 12px; border-radius: 2px;
}
.status-band[data-built="0"] .status-tag { background: var(--paper); color: var(--ink); border: 1px solid var(--ink); padding: 6px 11px; }
.status-note { font-size: 15px; color: var(--ink); max-width: 84ch; }
/* Nothing outside a phone styles anything inside one. The rule above this
   comment is the reason: a page selector with the same specificity as a widget
   selector wins on source order, and repaints app copy in page colours. */
.device p, .device h3 { margin: 0; max-width: none; }

/* ============================================================ device
   Built as live DOM, never a screenshot. It has to re-theme, and a screenshot
   of this app would carry the previous client's brand. The screen reads the
   same tokens as the page, so the theme switch re-themes every phone. */

.device {
  --dev-w: 300px;
  width: var(--dev-w);
  background: var(--bezel);
  border-radius: 42px;
  padding: 9px;
  box-shadow: 0 0 0 1px var(--bezel-edge);
  flex: none;
  transition: background-color var(--beat) var(--ease);
}

.device-screen {
  background: var(--card);
  color: var(--ink);
  border-radius: 34px;
  overflow: hidden;
  height: calc(var(--dev-w) * 2.04);
  display: flex;
  flex-direction: column;
  position: relative;
  font-size: 11.5px;
  line-height: 1.4;
  transition: background-color var(--beat) var(--ease);
}

.scr-status {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 20px 3px;
  font-size: 10.5px; font-weight: 600; letter-spacing: -.01em;
  color: var(--ink); flex: none;
}
.scr-status .scr-right { display: flex; gap: 6px; align-items: center; }
.scr-status .sig { display: flex; gap: 2px; align-items: flex-end; }
.scr-status .sig i { width: 2.5px; background: var(--ink); border-radius: 1px; display: block; }
.scr-status .sig i:nth-child(4) { height: 10px; }
.scr-status .sig i:nth-child(1) { height: 4px; }
.scr-status .sig i:nth-child(2) { height: 6px; }
.scr-status .sig i:nth-child(3) { height: 8px; }
.scr-status .bat { width: 17px; height: 8px; border: 1px solid var(--ink); border-radius: 2px; position: relative; }
.scr-status .bat::after { content: ""; position: absolute; inset: 1.5px; right: 5px; background: var(--ink); border-radius: 1px; }

.scr-nav {
  flex: none;
  padding: 4px 16px 10px;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.scr-nav .scr-title { font-family: var(--display); font-size: 19px; font-weight: 700; letter-spacing: -.035em; }
.scr-nav .scr-badge {
  font-family: var(--mono); font-size: 8.5px; font-weight: 600; letter-spacing: .06em;
  background: var(--hue-soft); color: var(--ink); padding: 4px 7px; border-radius: 999px;
  white-space: nowrap;
}

.scr-body {
  flex: 1 1 auto;
  overflow: hidden;
  padding: 0 16px 12px;
  display: flex; flex-direction: column; gap: 9px;
}

.scr-tabbar {
  flex: none;
  border-top: 1px solid var(--rule);
  display: grid; grid-template-columns: repeat(5, 1fr);
  padding: 7px 4px 12px;
}
.scr-tabbar span {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  font-size: 7.5px; font-weight: 500; color: var(--ink-3); letter-spacing: -.01em;
}
.scr-tabbar span svg { width: 17px; height: 17px; }
.scr-tabbar span[data-on="1"] { color: var(--hue-ink); }

/* device widgets. The reds and ambers are tokens that do not flip, with white
   on them: a verdict is not a product hue and an alert is the same colour in
   the dark. They are declared once, in :root, and nowhere in the dark blocks. */

.w-alert {
  background: var(--alert); color: var(--on-alert); padding: 9px 10px; border-radius: 10px;
  display: flex; gap: 8px; align-items: flex-start;
}
.w-alert svg { width: 15px; height: 15px; flex: none; margin-top: 1px; }
.w-alert b { display: block; font-size: 11px; font-weight: 600; }
.w-alert small { display: block; font-size: 9.5px; color: var(--on-alert); margin-top: 1px; }
.w-alert .ack {
  margin-top: 6px; display: inline-block; background: var(--on-alert); color: var(--alert);
  font-size: 9px; font-weight: 600; padding: 4px 8px; border-radius: 5px;
}

.w-card { border: 1px solid var(--rule); padding: 9px 10px; border-radius: 11px; }

.w-post .who { display: flex; gap: 7px; align-items: center; margin-bottom: 6px; }
.w-post .who b { font-size: 10.5px; font-weight: 600; display: block; line-height: 1.2; }
.w-post .who small { font-size: 8.5px; color: var(--ink-2); display: block; }
.w-post .txt { font-size: 10.5px; color: var(--ink); }
.w-post .react {
  display: flex; gap: 10px; margin-top: 7px; padding-top: 7px;
  border-top: 1px solid var(--rule-2); color: var(--ink-2); font-size: 9px;
  align-items: center;
}
.w-post .react svg { width: 12px; height: 12px; vertical-align: -2px; margin-right: 3px; }

.av {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--display); font-size: 10px; font-weight: 700;
  letter-spacing: -.02em;
  background: var(--hue-soft); color: var(--ink);
}

.w-kudos { background: var(--hue-soft); border-radius: 11px; padding: 9px 10px; }
.w-kudos .line { font-size: 10.5px; }
.w-kudos .line b { font-weight: 600; }
.w-kudos .val {
  display: inline-block; margin-top: 6px; background: var(--hue); color: var(--on-hue);
  font-family: var(--mono); font-size: 7.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; padding: 3px 6px; border-radius: 4px;
}

.w-rows { display: flex; flex-direction: column; }
.w-row {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 0; border-bottom: 1px solid var(--rule-2);
}
.w-row:last-child { border-bottom: 0; }
.w-row .lead {
  width: 34px; flex: none; text-align: center;
  font-family: var(--mono); font-size: 8px; font-weight: 600;
  letter-spacing: .04em; color: var(--ink-2); line-height: 1.25;
}
.w-row .mid { flex: 1 1 auto; min-width: 0; }
.w-row .mid b { display: block; font-size: 10.5px; font-weight: 600; letter-spacing: -.01em; }
.w-row .mid small { display: block; font-size: 9px; color: var(--ink-2); }
.w-row .end { flex: none; font-size: 9px; color: var(--ink-2); text-align: right; font-family: var(--mono); letter-spacing: .02em; }
.w-row .end.hot { color: var(--hue-ink); font-weight: 600; }

.w-scan {
  border: 1px solid var(--rule); border-radius: 11px; overflow: hidden;
}
/* A camera lens is black in both themes: --lens is declared once. */
.w-scan .lens {
  height: 84px; background: var(--lens); position: relative;
  display: grid; place-items: center;
}
.w-scan .lens .frame {
  width: 108px; height: 56px; border: 2px solid var(--on-lens); border-radius: 6px; opacity: .9;
}
.w-scan .lens .code {
  position: absolute; display: flex; gap: 2px; align-items: center;
}
.w-scan .lens .code i { display: block; width: 2px; height: 30px; background: var(--on-lens); }
.w-scan .lens .code i:nth-child(2n) { height: 22px; width: 3px; }
.w-scan .lens .code i:nth-child(3n) { height: 34px; width: 1px; }
.w-scan .out { padding: 9px 10px; }
.w-scan .out b { font-size: 11px; font-weight: 600; display: block; }
.w-scan .out small { font-size: 9px; color: var(--ink-2); display: block; margin-top: 1px; }

.w-flags { display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.w-flag { display: flex; align-items: center; gap: 7px; font-size: 9.5px; }
.w-flag .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
/* status fills, not product hues: #378 took Social out of meaning success and
   this line put it back. They take the brand's dark fills in the dark. */
.w-flag .dot.ok { background: var(--verdict-ok); }
.w-flag .dot.no { background: var(--verdict-no); }
.w-flag .dot.mid { background: var(--verdict-mid); }

.w-approve { border: 1px solid var(--rule); border-radius: 12px; padding: 10px; }
.w-approve .amt { font-family: var(--display); font-size: 25px; font-weight: 700; letter-spacing: -.04em; line-height: 1; }
.w-approve .meta { font-size: 9.5px; color: var(--ink-2); margin-top: 4px; }
.w-approve .btns { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5px; margin-top: 9px; }
.w-approve .btns span {
  text-align: center; font-size: 8.5px; font-weight: 600; padding: 6px 2px;
  border-radius: 6px; border: 1px solid var(--rule); color: var(--ink-2); letter-spacing: -.01em;
}
.w-approve .btns span:first-child { background: var(--hue); color: var(--on-hue); border-color: var(--hue); }

.w-chips { display: flex; gap: 5px; flex-wrap: wrap; }
.w-chip {
  font-family: var(--mono); font-size: 8px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; padding: 4px 7px; border-radius: 999px;
  border: 1px solid var(--rule); color: var(--ink-2);
}
.w-chip[data-on="1"] { background: var(--hue); color: var(--on-hue); border-color: var(--hue); }

/* an app footnote, in the app's own voice. Not a caption about the app. */
.w-note { font-size: 9px; color: var(--ink-3); line-height: 1.45; }

.w-tr {
  margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--rule);
  font-size: 10px; color: var(--ink-2);
}
.w-tr-lab {
  display: block; font-family: var(--mono); font-size: 7.5px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--hue-ink); margin-bottom: 3px;
}

.w-poll .q { font-size: 10.5px; font-weight: 600; margin-bottom: 8px; }
.w-poll .opt { display: flex; align-items: center; gap: 7px; margin-bottom: 5px; font-size: 9.5px; }
.w-poll .opt .lab { width: 66px; flex: none; color: var(--ink-2); }
.w-poll .opt .tr { flex: 1 1 auto; height: 6px; background: var(--shade); border-radius: 99px; overflow: hidden; }
.w-poll .opt .tr i { display: block; height: 100%; background: var(--hue); border-radius: 99px; }
.w-poll .opt .n { width: 12px; flex: none; text-align: right; font-family: var(--mono); font-size: 8.5px; }
.w-poll .tot { font-family: var(--mono); font-size: 8px; letter-spacing: .06em; color: var(--ink-3); margin-top: 6px; }

.w-consent { border: 1px solid var(--rule); border-radius: 12px; padding: 10px; }
.w-consent .hd { display: flex; gap: 7px; align-items: center; color: var(--hue-ink); }
.w-consent .hd svg { width: 16px; height: 16px; flex: none; }
.w-consent .hd b { font-size: 11px; font-weight: 600; color: var(--ink); letter-spacing: -.02em; }
.w-consent p { font-size: 9.5px; color: var(--ink-2); margin-top: 6px; }
.w-consent .cta {
  display: block; text-align: center; margin-top: 9px; background: var(--hue); color: var(--on-hue);
  font-size: 9.5px; font-weight: 600; padding: 7px 8px; border-radius: 8px;
}

.w-compose { border: 1px solid var(--rule); border-radius: 12px; padding: 9px 10px; }
.w-compose .ph { display: block; font-size: 10.5px; color: var(--ink-3); }
.w-compose .pills { display: flex; gap: 5px; margin-top: 8px; flex-wrap: wrap; }
.w-compose .pills span {
  font-size: 8.5px; font-weight: 500; color: var(--ink-2);
  border: 1px solid var(--rule); padding: 4px 8px; border-radius: 999px;
}

.w-rows-head {
  font-family: var(--mono); font-size: 8px; font-weight: 600; letter-spacing: .11em;
  text-transform: uppercase; color: var(--ink-3); margin-top: 2px;
}

.w-amber, .w-sos { border-radius: 12px; padding: 11px; }
.w-amber { background: var(--amber); color: var(--on-amber); }
.w-sos { background: var(--sos); color: var(--on-sos); }
.w-amber .eb, .w-sos .eb {
  font-family: var(--mono); font-size: 7.5px; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: inherit; display: block;
}
.w-amber b, .w-sos b { display: block; font-size: 12.5px; font-weight: 600; margin-top: 5px; letter-spacing: -.02em; }
.w-amber p, .w-sos p { font-size: 9.5px; margin-top: 4px; color: inherit; }
.w-amber .ack {
  display: inline-block; margin-top: 8px; background: var(--on-amber); color: var(--amber);
  font-size: 9.5px; font-weight: 600; padding: 5px 10px; border-radius: 6px;
}

.w-hold { display: flex; flex-direction: column; align-items: center; padding: 6px 0 2px; }
.w-hold .ring {
  width: 96px; height: 96px; border-radius: 50%; border: 3px solid var(--rule);
  display: grid; place-items: center;
}
.w-hold .core {
  width: 74px; height: 74px; border-radius: 50%; background: var(--alert); color: var(--on-alert);
  display: grid; place-items: center;
}
.w-hold .core svg { width: 30px; height: 30px; }
.w-hold b {
  font-family: var(--mono); font-size: 9px; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; margin-top: 9px;
}
.w-hold small { font-size: 9px; color: var(--ink-2); margin-top: 2px; }

.w-track .steps { display: flex; justify-content: space-between; gap: 2px; }
.w-track .steps span {
  flex: 1 1 0; min-width: 0; font-size: 7px; color: var(--ink-3);
  display: flex; flex-direction: column; gap: 5px; letter-spacing: -.01em;
}
.w-track .steps i {
  display: block; height: 4px; border-radius: 99px; background: var(--shade);
}
.w-track .steps span[data-on="1"] { color: var(--ink); font-weight: 600; }
.w-track .steps span[data-on="1"] i { background: var(--hue); }

.w-field { border: 1px solid var(--rule); border-radius: 11px; padding: 9px 10px; }
.w-field .lab {
  font-family: var(--mono); font-size: 7.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}
.w-field p { font-size: 10.5px; margin-top: 5px; }

.w-cta {
  background: var(--hue); color: var(--on-hue); text-align: center;
  font-size: 10px; font-weight: 600; padding: 9px; border-radius: 9px;
}

.w-stmt { background: var(--hue-soft); border-radius: 11px; padding: 10px; }
.w-stmt .lab {
  font-family: var(--mono); font-size: 7.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-2); display: block;
}
.w-stmt b { font-family: var(--display); font-size: 24px; font-weight: 700; letter-spacing: -.04em; display: block; line-height: 1.1; }
.w-stmt small { font-size: 9.5px; color: var(--ink-2); }

.w-outcome { border-left: 3px solid var(--hue); padding: 2px 0 2px 10px; }
.w-outcome .lab {
  font-family: var(--mono); font-size: 7.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--hue-ink); display: block;
}
.w-outcome b { font-size: 11px; font-weight: 600; display: block; margin-top: 3px; }
.w-outcome p { font-size: 9.5px; color: var(--ink-2); margin-top: 4px; }

.w-ask {
  display: flex; gap: 8px; align-items: center; border: 1px solid var(--hue);
  border-radius: 999px; padding: 8px 12px; font-size: 10px; color: var(--ink);
}
.w-ask svg { width: 14px; height: 14px; flex: none; color: var(--hue-ink); }

.w-scan .grade { display: flex; gap: 3px; margin-top: 7px; }
.w-scan .grade span {
  width: 17px; height: 15px; display: grid; place-items: center; border-radius: 3px;
  font-family: var(--mono); font-size: 8px; font-weight: 400;
  background: var(--shade); color: var(--ink-2); border: 1px solid var(--rule);
}
.w-scan .grade span[data-on="1"] { background: var(--ink); color: var(--paper); border-color: var(--ink); font-weight: 600; }

/* ============================================================ shipped
   The section that says plainly what exists. Unusual on a marketing page and
   the reason to trust the rest of it. Each row carries its product's plate as
   a solid block, because a fact about a product should wear the product. */

.ship { padding-block: clamp(46px, 5.6vw, 76px); }

.ship-list { margin-top: clamp(28px, 3.4vw, 48px); border-top: 1px solid var(--ink); }
.ship-list li {
  display: grid; grid-template-columns: 14px minmax(0, 1fr);
  gap: clamp(16px, 2.2vw, 30px); align-items: stretch;
  padding: clamp(20px, 2.4vw, 30px) 0; border-bottom: 1px solid var(--rule);
}
.ship-dot { width: 14px; border-radius: 2px; background: var(--plate); }
.ship-list h3 { font-size: clamp(22px, 2.2vw, 30px); letter-spacing: -.035em; display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.ship-list > li > div > p { color: var(--ink-2); margin-top: 10px; max-width: 68ch; font-size: 16px; }

.ship-tag {
  font-family: var(--mono); font-size: 9.5px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; padding: 4px 9px; border-radius: 999px;
  border: 1px solid var(--rule); color: var(--ink-2);
}
.ship-tag[data-built="1"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.ship-sub { margin-top: clamp(34px, 4vw, 56px); }
/* The hairlines are drawn by each cell rather than by the gap showing a
   coloured background through it, so an empty track is simply empty at every
   count and every width. */
.ship-notes {
  margin-top: 20px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1px; background: var(--paper); padding: 1px;
}
.ship-notes > div { background: var(--paper); padding: 20px; box-shadow: 0 0 0 1px var(--rule); }
.ship-notes dt {
  font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .11em;
  text-transform: uppercase; color: var(--ink);
}
.ship-notes dd { margin-top: 9px; font-size: 14.5px; color: var(--ink-2); }

/* ============================================================ lexicon */

.lex { padding-block: clamp(46px, 5.6vw, 76px); }
.lex-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 30rem); gap: clamp(20px, 4vw, 60px); align-items: end; }
.lex-head .lede { margin-top: 0; }

.lex-scroll, .mx-scroll { overflow-x: auto; margin-top: clamp(26px, 3.4vw, 48px); }
.lex-scroll:focus-visible, .mx-scroll:focus-visible { outline-offset: 6px; }

.lext { width: 100%; min-width: 640px; border-collapse: collapse; }
.lext th, .lext td { text-align: left; padding: 14px 16px 14px 0; border-bottom: 1px solid var(--rule); }
.lext thead th {
  font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .11em;
  text-transform: uppercase; border-bottom: 1px solid var(--ink); white-space: nowrap; color: var(--ink);
}
.lext thead th span { display: inline-flex; align-items: center; gap: 8px; }
.lext thead th i { width: 11px; height: 11px; border-radius: 50%; display: block; flex: none; background: var(--plate); }
.lext tbody th, .lext thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--paper); padding-right: 18px; }
.lext tbody th {
  font-family: var(--mono); font-size: 10px; font-weight: 400; letter-spacing: .11em;
  text-transform: uppercase; color: var(--ink-2); width: 20%; white-space: nowrap;
}
.lext tbody td {
  font-family: var(--display); font-size: clamp(22px, 2.3vw, 34px); font-weight: 600;
  letter-spacing: -.035em; line-height: 1.05; width: 20%; color: var(--plate-ink);
}

/* the per-product strip on a product page */
.lexs { padding-block: clamp(40px, 5vw, 68px); }
.lexs-grid { margin-top: 26px; border-top: 1px solid var(--ink); }
.lexs-row {
  display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 48px); align-items: baseline;
  padding: clamp(13px, 1.6vw, 20px) 0; border-bottom: 1px solid var(--rule);
}
.lex-key { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-2); }
.lex-val { font-family: var(--display); font-size: clamp(26px, 3.2vw, 42px); font-weight: 600; letter-spacing: -.04em; line-height: 1; color: var(--hue-ink); }

/* ============================================================ capabilities
   Sticky phone on the left, an index on the right. The composition flips from
   the hero on purpose: the page must not be a stack of the same layout. */

.scene { padding-block: clamp(42px, 5.5vw, 76px) clamp(28px, 4vw, 60px); }
.scene-head { max-width: 46rem; }

.scene-grid {
  display: grid; grid-template-columns: minmax(0, 452px) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 80px); align-items: start;
  margin-top: clamp(30px, 4vw, 58px);
}

.scene-stage {
  position: sticky; top: calc(var(--bar-h) + clamp(18px, 3vw, 44px));
  display: flex; flex-direction: column; align-items: center; gap: 16px;
}
/* Scaled rather than widened. `.device-screen` is `--dev-w * 2.04` tall and
   every widget inside it is set in absolute pixels, so raising --dev-w alone
   makes a taller frame around the same small screen. `zoom` scales the layout
   and the type together and still reports a real box to the sticky column.
   Where zoom is not supported the phone renders at 344. */
.scene-stage .device { --dev-w: 344px; zoom: 1.2; }
.stage-cap { text-align: center; max-width: 46ch; }
.scene-swap { transition: opacity 190ms linear; }
.scene-swap.fading { opacity: 0; }

.scene-list { min-width: 0; }

.cap { border-top: 1px solid var(--rule); padding: clamp(26px, 3.2vw, 42px) 0; position: relative; }
.cap:last-child { border-bottom: 1px solid var(--rule); }
.cap::before {
  content: ""; position: absolute; left: 0; top: -1px; height: 3px; width: 0;
  background: var(--hue); transition: width 420ms var(--ease);
}
.cap[data-live="1"]::before { width: 100%; }

.cap-key { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); transition: color 300ms var(--ease); }
.cap[data-live="1"] .cap-key { color: var(--hue-ink); }

.cap > h3 { font-size: clamp(23px, 2.5vw, 33px); letter-spacing: -.04em; margin: 10px 0 0; }
.cap > p { color: var(--ink-2); margin-top: 12px; max-width: 52ch; }

.cap-facts { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 16px; }
.cap-facts li {
  font-family: var(--mono); font-size: 11px; font-weight: 400; letter-spacing: -.01em;
  color: var(--ink-2);
  border: 1px solid var(--rule); padding: 6px 11px; border-radius: 999px;
}

/* the phone each capability carries. It is the source the sticky stage moves,
   and on a narrow screen it is shown in place instead. Without the script
   there is no stage to move it to, so every capability keeps its own phone
   and the sticky column is dropped. Nothing is only reachable by script. */
.cap-see { display: flex; justify-content: center; margin-top: 20px; }
.js .cap-see { display: none; }
html:not(.js) .scene-stage { display: none; }
html:not(.js) .scene-grid { grid-template-columns: minmax(0, 1fr); }

/* ============================================================ matrix */

.matrix { padding-block: clamp(46px, 5.6vw, 76px); }
.mx { width: 100%; min-width: 820px; border-collapse: collapse; font-size: 15px; }
.mx caption { text-align: left; }
.mx th, .mx td { text-align: left; padding: 13px 16px 13px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
.mx thead th {
  font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .11em;
  text-transform: uppercase; border-bottom: 1px solid var(--ink); white-space: nowrap; color: var(--ink);
}
.mx thead th span { display: inline-flex; align-items: center; gap: 8px; }
.mx thead th i { width: 11px; height: 11px; border-radius: 50%; display: block; flex: none; background: var(--plate); }
/* the capability name stays put while the four product columns scroll under
   it, otherwise a narrow screen loses the row it is reading */
.mx tbody th, .mx thead th:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--paper); padding-right: 20px;
}
.mx tbody th { font-family: var(--body); font-weight: 500; font-size: 15.5px; letter-spacing: -.01em; width: 28%; }
.mx tbody tr:hover th { background: var(--rule-2); }
.mx tbody th small { display: block; font-weight: 400; color: var(--ink-2); font-size: 13px; margin-top: 4px; }
.mx td { color: var(--ink); font-size: 14px; width: 18%; }
.mx td .mk { display: inline-flex; align-items: flex-start; gap: 8px; }
.mx td .mk i { width: 9px; height: 9px; border-radius: 50%; flex: none; display: block; margin-top: 5px; background: var(--plate); }
.mx td[data-has="0"] { color: var(--ink-3); }
.mx td[data-has="0"] .mk i { background: transparent; box-shadow: inset 0 0 0 1.5px var(--rule-strong); }
.mx tbody tr:hover td, .mx tbody tr:hover th { background: var(--rule-2); }

.mx-legend, .lex-scroll + .note-long { margin-top: 18px; }
.mx-legend { display: flex; flex-wrap: wrap; gap: 20px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }

/* ============================================================ access */

.sec { padding: clamp(46px, 5.6vw, 76px) 0; background: var(--shade); transition: background-color var(--beat) var(--ease); }
.sec .note-long { color: var(--ink-2); }
.sec-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(28px, 5vw, 76px); align-items: start; margin-top: clamp(28px, 3.6vw, 50px); }

.trace { background: var(--card); border: 1px solid var(--rule); font-family: var(--mono); font-size: 11px; line-height: 1.7; letter-spacing: -.01em; }
.trace-head {
  padding: 11px 16px; border-bottom: 1px solid var(--rule);
  font-size: 9.5px; font-weight: 600; letter-spacing: .11em; text-transform: uppercase;
  color: var(--ink-2); display: flex; justify-content: space-between; gap: 10px;
}
.trace ol { padding: 12px 16px 16px; }
.trace li { display: grid; grid-template-columns: 54px 1fr; gap: 12px; padding: 6px 0; }
.trace li .verb { color: var(--ink-3); }
.trace li b { font-weight: 600; }
.trace li .ok { color: var(--corp-ink); }

/* The trace writes itself in as it enters view, one line after another, the
   way the requests run. Scroll-driven and script-free; where unsupported the
   lines are simply there. */
@supports (animation-timeline: view()) {
  .trace li { animation: trace-in linear both; animation-timeline: view(); animation-range: entry 0% entry 90%; }
}
@keyframes trace-in { from { opacity: 0; transform: translate3d(-8px, 0, 0); } }

.sec-list li { border-top: 1px solid var(--rule); padding: 20px 0; }
.sec-list li:last-child { border-bottom: 1px solid var(--rule); }
.sec-list h3 { font-size: 20px; letter-spacing: -.03em; }
.sec-list > li > p { color: var(--ink-2); margin-top: 9px; font-size: 16px; }

/* ============================================================ close, footer */

.close { padding-block: clamp(52px, 6.5vw, 96px); }
.close-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 24rem); gap: clamp(26px, 5vw, 72px); align-items: center; }
.close h2 { font-size: clamp(36px, 5.2vw, 72px); letter-spacing: -.045em; margin-top: 16px; }
.close-act { margin-top: 28px; }
.close-mark { display: flex; flex-direction: column; align-items: center; }
.big-mark { width: min(240px, 60vw); aspect-ratio: 1; }
.close-mark .note-long { text-align: center; max-width: 34ch; }

.foot { border-top: 1px solid var(--ink); padding-block: 34px 48px; }
.foot-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 28px; }
.foot-h { font-family: var(--mono); font-size: 9.5px; font-weight: 600; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 12px; }
.foot li { padding: 5px 0; font-size: 15px; color: var(--ink-2); }
.foot li b { color: var(--ink); font-weight: 500; }
.foot li small { display: block; font-family: var(--mono); font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); margin-top: 2px; }
.foot-end {
  margin-top: 34px; padding-top: 18px; border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
}

/* ============================================================ motion
   The tab change. Where the browser has View Transitions the active plate
   glides from one tab to the next while the page cross-fades on the site's
   one beat; www/site.js still swaps <main> and still falls back to a plain
   fade where they are missing. */

main { transition: opacity 180ms linear; view-transition-name: main; }
main.leaving { opacity: 0; }
.world-tab[aria-current="page"] { view-transition-name: active-tab; }

:root.nav::view-transition-old(main) { animation: 160ms linear both fade-out; }
:root.nav::view-transition-new(main) { animation: var(--beat) var(--ease) both page-in; }
::view-transition-group(active-tab) { animation-duration: var(--beat); animation-timing-function: var(--ease); }
@keyframes fade-out { to { opacity: 0; } }
@keyframes page-in { from { opacity: 0; transform: translate3d(0, 14px, 0); } }

/* ============================================================ responsive */

@media (max-width: 1180px) {
  .hero-product { gap: 10px; align-items: start; }
  .hero-home { grid-template-columns: minmax(0, 1.4fr) minmax(0, 360px); }
  .scene-grid { grid-template-columns: minmax(0, 352px) minmax(0, 1fr); gap: 34px; }
  .scene-stage .device { --dev-w: 324px; zoom: 1; }
  .sec-grid, .close-grid, .lex-head { grid-template-columns: minmax(0, 1fr); }
  .close-grid { gap: 34px; align-items: start; }
  .close-mark { align-items: flex-start; }
  .close-mark .note-long { text-align: left; }
}

@media (max-width: 980px) {
  /* The ring goes above the words, small, and still draws. */
  .hero-home { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .hero-ring { width: clamp(120px, 26vw, 200px); justify-self: start; order: -1; margin-bottom: 8px; }
}

@media (max-width: 860px) {
  :root { --bar-h: 58px; }

  .brand-name { display: none; }
  .world-tab { flex-direction: column; gap: 3px; padding: 7px 4px; font-size: 8.5px; letter-spacing: .07em; }
  .world-tab .disc { width: 19px; height: 19px; }
  .world-tab .disc svg { width: 12px; height: 12px; }
  .theme { padding: 0 12px; }
  .theme-lab { display: none; }

  /* the sticky phone is dropped: at this width it would eat the viewport.
     Each capability shows its own phone in place instead, which is also what
     a visitor with the script switched off gets at any width. */
  .scene-grid { grid-template-columns: minmax(0, 1fr); }
  .scene-stage { display: none; }
  .js .cap-see { display: flex; justify-content: center; }

  /* the shelf becomes a strip that snaps, phone by phone */
  .shelf .shell { padding-right: 0; }
  .strip { overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scrollbar-width: none; padding-right: var(--gut); gap: 18px; }
  .strip::-webkit-scrollbar { display: none; }
  .strip-item { flex: none; scroll-snap-align: start; }
  .strip-item:nth-child(2n) { margin-top: 0; }

  .status { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .status-tag { justify-self: start; }

  .lexs-row { grid-template-columns: minmax(0, 1fr); gap: 3px; padding: 13px 0; }
  .ship-list li { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .ship-dot { height: 4px; width: 44px; }
}

@media (max-width: 520px) {
  body { font-size: 16px; }
  .hero h1 { font-size: clamp(33px, 9.6vw, 46px); }
  .creed li { gap: 8px; }
  .creed-no { font-size: .5em; }
  .btn { width: 100%; justify-content: center; }
  .foot-end { flex-direction: column; gap: 8px; }
  .close-mark .big-mark { width: 190px; }
}

/* ============================================================ reduced motion
   Travel goes. Colour, cross-fade and the sticky stage stay, so the page still
   explains itself with every animation off. The creed is struck, the ring is
   closed and coloured, the phones are on the shelf: the meaning is in the end
   state, so it arrives whole. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .swap-in, .swap.in .swap-in { transition: opacity 140ms linear; transform: none; }
  .cap::before { transition: none; }
  .strip-item, .strip-link .device, .strip-link:hover .device, .strip-link:focus-visible .device { transition: none; transform: none; }
  .world-tab .disc, .world-tab:hover .disc, .world-tab:focus-visible .disc { transform: none; }
  main, main.leaving { transition: none; opacity: 1; }

  .creed li, .hero-home .lede, .hero-home .hero-act, .hero-home .eyebrow { animation: none; opacity: 1; transform: none; }
  .creed-thing::after { animation: none; transform: scaleX(1); }
  h1.creed-turn { animation: none; color: var(--ink); }
  .ring-ink path { animation: none; stroke-dashoffset: 0; }
  .ring-hue { animation: none; opacity: 1; }
  .ring-node { animation: none; transform: none; }
  .strip-item, .shelf .w-poll .opt .tr i, .trace li { animation: none; opacity: 1; transform: none; }

  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }

  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}

/* ── The three pillar heroes ─────────────────────────────────────────────────
 *
 * There is no shared pillar hero. There are three, and the only thing they
 * hold in common is the standfirst, where the swapping noun lives:
 *
 *   .roll  CORP, a sequence. Its problem is a problem in time, so the hero is
 *          three moments of a rollout under a rule that draws across them.
 *   .quo   FAITH, a quotation. The congregation's own seeded sentence, set as
 *          the h1 with the open quote hanging into the margin, its three
 *          sibling values ruled underneath.
 *   .rec   ESTATE, a record. Five questions a household is asked and where each
 *          answer lives, set small, ruled and right-aligned like a filed
 *          document. The quietest hero on the site.
 *
 * Each h1 rule is a two-class selector so it beats `.hero h1`, including inside
 * the 520px block. */

.standfirst { color: var(--ink-3); }

/* ---- corp: the sequence */

.roll {
  position: relative;
  border-top: 1px solid var(--rule);
  padding-top: clamp(16px, 2vw, 26px);
  margin: clamp(20px, 2.6vw, 34px) 0 clamp(26px, 3.2vw, 44px);
}
/* The rule draws left to right, once, on the site's own beat. It is the
   argument: the three stamps under it are a line of time. Same idiom as the
   creed's strike, in the pillar's own colour rather than a second one. */
.roll::before {
  content: "";
  position: absolute; left: 0; top: -1px; width: 100%; height: 2px;
  background: var(--hue-ink);
  transform: scaleX(0); transform-origin: left center;
  animation: roll-draw .9s var(--draw) .2s forwards;
}
@keyframes roll-draw { to { transform: scaleX(1); } }

.roll-list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.6vw, 44px);
  max-width: 60rem;
}
.roll-list li { opacity: 0; animation: rise .5s var(--ease) forwards; }
.roll-list li:nth-child(1) { animation-delay: .25s; }
.roll-list li:nth-child(2) { animation-delay: .55s; }
.roll-list li:nth-child(3) { animation-delay: .85s; }
.roll-when {
  display: block;
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase; color: var(--hue-ink);
}
.roll-what {
  display: block; margin-top: 11px;
  font-family: var(--display); font-size: clamp(19px, 2.1vw, 28px); font-weight: 600;
  letter-spacing: -.035em; line-height: 1.14;
  color: var(--ink-2);
}
/* The turn and the argument sit side by side, under a rule that spans the same
   width as both of them. Corp is the pillar that argues with a buyer who is
   comparing vendors, so it is the busiest of the three heroes, and the only one
   in two columns. */
.roll-turn-band {
  display: grid; grid-template-columns: minmax(0, 1.04fr) minmax(0, 30rem);
  gap: clamp(24px, 4vw, 68px); align-items: start;
}
.roll-turn-band .lede { margin-top: 0; max-width: 46ch; }
.hero-product .roll-turn {
  font-size: clamp(30px, 4.2vw, 56px);
  line-height: 1.02; letter-spacing: -.04em;
  margin: 0; max-width: 15ch;
}

/* ---- faith: the quotation */

.hero-product .quo {
  font-size: clamp(31px, 4.8vw, 64px);
  line-height: 1.04; letter-spacing: -.04em;
  margin: clamp(16px, 2vw, 26px) 0 0;
  max-width: 18ch;
  /* Hanging punctuation, done so it cannot overflow the gutter. .45em is the
     glyph's own advance in Familjen Grotesk at this weight, measured. */
  padding-left: .45em; text-indent: -.45em;
}
/* The marks arrive first, in the pillar's colour, and the sentence follows
   them: it is somebody else's sentence, and the marks say so. */
.hero-product .quo::before { content: "\201C"; color: var(--hue-ink); }
.hero-product .quo::after { content: "\201D"; color: var(--hue-ink); }
.hero-product .quo::before, .hero-product .quo::after { display: inline-block; opacity: 0; animation: rise .5s var(--ease) .1s forwards; }
.hero-product .quo::after { animation-delay: .5s; }

.quo-cite { margin-top: 18px; max-width: 82ch; }

.quo-rest {
  margin: clamp(22px, 3vw, 36px) 0 0;
  border-top: 1px solid var(--ink);
  max-width: 52rem;
}
.quo-rest > div {
  display: grid; grid-template-columns: minmax(0, 9rem) minmax(0, 1fr);
  gap: clamp(12px, 2vw, 28px); align-items: baseline;
  padding: 14px 0; border-bottom: 1px solid var(--rule);
}
.quo-rest dt {
  font-family: var(--display); font-size: clamp(17px, 1.6vw, 21px); font-weight: 700;
  letter-spacing: -.03em; color: var(--hue-ink);
}
.quo-rest dd { margin: 0; color: var(--ink-2); font-size: 16px; }

/* ---- estate: the record */

.rec {
  margin: clamp(20px, 2.6vw, 32px) 0 clamp(26px, 3.2vw, 42px);
  border-top: 1px solid var(--ink);
  max-width: 48rem;
}
.rec > div {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 14rem);
  gap: 16px; align-items: baseline;
  padding: 13px 0; border-bottom: 1px solid var(--rule);
  opacity: 0; animation: rise .45s var(--ease) forwards;
}
/* The record files itself in, one row after another, top to bottom. */
.rec > div:nth-child(1) { animation-delay: .10s; }
.rec > div:nth-child(2) { animation-delay: .22s; }
.rec > div:nth-child(3) { animation-delay: .34s; }
.rec > div:nth-child(4) { animation-delay: .46s; }
.rec > div:nth-child(5) { animation-delay: .58s; }
.rec > div:nth-child(6) { animation-delay: .70s; }
.rec dt {
  font-family: var(--display); font-size: clamp(16px, 1.5vw, 21px); font-weight: 600;
  letter-spacing: -.025em; color: var(--ink);
}
.rec dd {
  margin: 0; text-align: right;
  font-family: var(--mono); font-size: 11px; letter-spacing: .01em; color: var(--ink-2);
}
.rec .rec-head { border-bottom-color: var(--rule-strong); padding-bottom: 9px; }
.rec .rec-head dt, .rec .rec-head dd {
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3);
}
/* The one restricted entry. It is restricted in the fixture too, so the colour
   is reporting a fact rather than emphasising a word. */
.rec [data-held="1"] dd { color: var(--hue-ink); font-weight: 600; }
.hero-product .rec-turn {
  font-size: clamp(25px, 3.1vw, 42px);
  line-height: 1.08; letter-spacing: -.035em;
  margin: 0; max-width: 23ch;
}

/* ── The appeal ──────────────────────────────────────────────────────────────
 *
 * Nothing has shipped to a store, so there is no download to offer. What a
 * reader of an in-build page wants is to be told when it opens, so the block
 * says that on the same soft field the status band uses. Corp gets ink on
 * white instead, because Corp runs today. */

.appeal { padding-block: clamp(48px, 6vw, 84px); }

.appeal-card {
  max-width: 46rem;
  padding: clamp(24px, 3.2vw, 48px);
  border: 1px solid var(--ink);
}
.appeal-card[data-built="0"] { background: var(--hue-soft); border-color: transparent; }
.appeal-card h2 {
  font-size: clamp(24px, 2.9vw, 40px); letter-spacing: -.035em; line-height: 1.06;
  margin: 14px 0 0; max-width: 20ch;
}
.appeal-body { color: var(--ink-2); font-size: 16px; margin-top: 15px; max-width: 58ch; }
.appeal-act { margin-top: clamp(22px, 2.6vw, 32px); }
.appeal-else { margin-top: 24px; max-width: 60ch; }

@media (prefers-reduced-motion: reduce) {
  /* Drawn, not undrawn: the rule is the sequence, so it arrives whole rather
     than being removed along with the motion. Same decision as the creed. */
  .roll::before { animation: none; transform: scaleX(1); }
  .roll-list li, .rec > div, .hero-product .quo::before, .hero-product .quo::after { animation: none; opacity: 1; }
}

@media (max-width: 980px) {
  .roll-turn-band { grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
  .roll-turn-band .lede { margin-top: 4px; max-width: 60ch; }
  .hero-product .roll-turn { max-width: 21ch; }
}

@media (max-width: 700px) {
  .roll-list { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .quo-rest > div { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 13px 0; }
  .rec > div { grid-template-columns: minmax(0, 1fr) minmax(0, 9rem); gap: 12px; }
  .rec dd { font-size: 10px; }
}

/* ── The plain pages ─────────────────────────────────────────────────────────
 *
 * /security/, /pricing/ and /about/. One column, the standfirst above an h1
 * that is a sentence rather than a name, then sections in the same anatomy as
 * the home page's ledgers: a ruled list of term and detail, because a security
 * review reads a record and not a brochure. The pricing plans are the one
 * three-column moment, and each column wears its pillar's plate. */

.hero-page { grid-template-columns: minmax(0, 1fr); padding-right: var(--gut); }
.hero-page .hero-words { max-width: 60rem; }
.hero .page-h1 { font-size: clamp(34px, 4.6vw, 64px); letter-spacing: -.04em; line-height: 1.0; max-width: 20ch; margin-top: 16px; }
.hero-page .lede { max-width: 62ch; }

.pg { padding-block: clamp(42px, 5.2vw, 72px); }
.pg-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 30rem); gap: clamp(20px, 4vw, 60px); align-items: end; }
.pg-head .lede { margin-top: 0; }
.pg .h-sec { font-size: clamp(30px, 3.8vw, 52px); }

.prose { margin-top: clamp(22px, 2.6vw, 34px); max-width: 66ch; display: grid; gap: 16px; }
.prose p { font-size: clamp(17px, 1.25vw, 18px); color: var(--ink-2); }

.facts { margin-top: clamp(24px, 3vw, 40px); border-top: 1px solid var(--ink); max-width: 66rem; }
.facts > div {
  display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 48px); align-items: baseline;
  padding: clamp(14px, 1.8vw, 22px) 0; border-bottom: 1px solid var(--rule);
}
.facts dt { font-family: var(--display); font-size: clamp(17px, 1.6vw, 21px); font-weight: 600; letter-spacing: -.025em; }
.facts dd { color: var(--ink-2); font-size: 16px; max-width: 62ch; }

.ref-list { margin-top: clamp(24px, 3vw, 40px); border-top: 1px solid var(--ink); max-width: 66rem; }
.ref-list > div {
  display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 48px); align-items: baseline;
  padding: clamp(16px, 2vw, 24px) 0; border-bottom: 1px solid var(--rule);
}
.ref-list dt { font-family: var(--display); font-size: clamp(24px, 2.4vw, 32px); white-space: nowrap; line-height: 1; letter-spacing: -.04em; display: flex; align-items: baseline; gap: .3em; }
.ref-list .creed-no { font-size: .5em; transform: none; }
.ref-noun { color: var(--refused); font-weight: 700; position: relative; }
.ref-noun::after { content: ""; position: absolute; left: -.04em; right: -.04em; top: .60em; height: .1em; background: var(--social-ink); border-radius: .03em; }
.ref-list dd { color: var(--ink-2); font-size: 16px; max-width: 60ch; }

.plans { margin-top: clamp(26px, 3.4vw, 44px); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; background: var(--paper); padding: 1px; }
.plan { background: var(--paper); box-shadow: 0 0 0 1px var(--rule); padding: clamp(20px, 2.4vw, 32px); border-top: 4px solid var(--plate); display: flex; flex-direction: column; }
.plan-name { font-family: var(--display); font-size: clamp(20px, 1.9vw, 26px); font-weight: 700; letter-spacing: -.035em; line-height: 1.1; color: var(--plate-ink); }
.plan-status { margin-top: 12px; }
.plan-how { margin-top: 16px; color: var(--ink-2); font-size: 15.5px; }
.plan-eb { margin-top: 22px; }
.plan-list { margin-top: 10px; border-top: 1px solid var(--ink); flex: 1 1 auto; }
.plan-list li { padding: 9px 0; border-bottom: 1px solid var(--rule); display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: baseline; font-size: 14px; }
.plan-list b { font-weight: 500; }
.plan-list small { font-family: var(--mono); font-size: 10px; color: var(--ink-3); letter-spacing: 0; text-align: right; }

@media (max-width: 1180px) { .pg-head { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 980px) { .plans { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 700px) {
  .facts > div, .ref-list > div { grid-template-columns: minmax(0, 1fr); gap: 6px; }
}
