/* Pekan OS landing page. Round 6 wave 3, design quality pass.

   Museo carries body copy and system chrome. Brigends is reserved for the
   feature headline, with Science Gothic on section subtitles. The shared
   brand foundation supplies all three owner-provided font families.

   Every colour here comes from the plan 4.1 token set the OS ships, so the
   page and the product read as one thing (finding 16).

   No em dashes in this file. */

@import url("../pekan/liquid-tokens.css");

:root {
  color-scheme: only dark;
  /* This exterior deliberately stays dark; don't inherit pale shell panels
     underneath its light navigation and preview lettering. */
  --pk-glass-surface: rgba(18, 18, 22, .9);
  --pk-glass-panel: rgba(30, 26, 38, .9);

  /* ===== ink, plan 4.1 ===== */
  --pm-purple: var(--pk-accent, #5956E9);
  --pm-purple-deep: var(--pk-accent-deep, #423EF3);
  --pm-lavender: var(--pk-accent-light, #838AFF);
  --pm-sun: #E4C56A;
  --pm-teal-bright: #3E9C9C;

  --g1-base: #0C0A12;
  --g2-rgb: 22, 18, 32;
  --g2-a: 0.78;
  --g2-bg: rgba(var(--g2-rgb), var(--g2-a));
  --g3-rgb: 28, 22, 42;
  --g3-a: 0.90;
  --g3-bg: rgba(var(--g3-rgb), var(--g3-a));
  --g3-blur: 32px;

  --ink: #F3F0FA;
  --ink-2: #C4C0D0;
  /* ink-3 was a duplicate of ink-2, so the type had two names for one value
     and no third tier. It is now a real third tier and still clears AA on
     the page ground at 13px and up. */
  --ink-3: #A4A0B4;

  --line: rgba(255, 255, 255, 0.10);
  --line-2: rgba(255, 255, 255, 0.18);
  --line-3: rgba(255, 255, 255, 0.28);

  /* Card surfaces. The old cards were a 6 percent lift that barely
     registered (finding 14). These are opaque, measured values that read as
     containers from across the room. */
  --card: #171326;
  --card-2: #1D1830;
  --card-line: rgba(255, 255, 255, 0.14);
  --card-line-2: rgba(255, 255, 255, 0.22);

  /* ===== radii, shared liquid tokens, SaaS exterior keeps sheet/control ===== */
  --r-win: var(--pk-radius-window, 24px);
  --r-sheet: var(--pk-radius-panel, 16px);
  --r-cta: var(--pk-radius-control, 10px);
  --r-btn: var(--pk-radius-control, 10px);
  --r-icon: 14px;
  --r-dock: var(--pk-radius-panel, 16px);

  /* ===== type scale =====
     A real scale at ratio 1.25 off a 16px base, so H1, H2, H3 and body each
     sit on their own step and nothing collides (findings 5 and 6).
       t-1 12.8  eyebrow and mono chrome
       t0   16   body small
       t1   20   body large, card copy
       t2   25   card title
       t3   31   section heading, small
       t4   39   section heading
       t5   49
       t6   61   H1 */
  --t--1: 0.8rem;
  --t-0: 1rem;
  --t-1: 1.25rem;
  --t-2: 1.5625rem;
  --t-3: 1.953rem;
  --t-4: 2.441rem;
  --t-5: 3.052rem;
  --t-6: 3.815rem;

  /* ===== spacing scale =====
     8pt, doubling. Every vertical gap on the page is one of these (finding
     12). Section rhythm is s-9 / s-8 / s-7 and nothing else. */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --s-9: 96px;
  --s-10: 128px;

  /* ===== the grid =====
     One container width, one gutter, everywhere. The old page had the text
     column at 1120 and the mockup running past it (finding 4). */
  --page: 1160px;
  --gutter: 32px;
  --nav-h: 64px;
  /* the measure every paragraph on the page is held to (finding 8) */
  --measure: 62ch;

  --focus: #A99BFF;
  --focus-halo: rgba(12, 10, 18, 0.85);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  --font: var(--pk-font);
  --mono: var(--pk-font);

  --logo-mark: var(--pm-purple-deep);
  --logo-word: var(--ink);
  --logo-dot: #2A2440;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  min-height: 100%;
  background: var(--g1-base);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

body {
  overflow-x: hidden;
}

img {
  max-width: 100%;
  height: auto;
}

a {
  color: var(--pm-lavender);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a:hover {
  color: var(--ink);
}

:focus {
  outline: none;
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--focus-halo);
}

.skip {
  position: absolute;
  left: var(--s-3);
  top: var(--s-3);
  z-index: 80;
  padding: 10px 14px;
  border-radius: var(--r-btn);
  background: var(--card-2);
  border: 1px solid var(--card-line-2);
  color: var(--ink);
  font-weight: 700;
  font-size: 14px;
  transform: translateY(-140%);
  text-decoration: none;
}

.skip:focus,
.skip:focus-visible {
  transform: none;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ===== atmosphere =====
   The old page ran a violet field behind everything and a different violet
   inside the mockup, six inches apart (finding 16). Both now come from
   --pm-purple, and the field is calmer so the cards can be the brightest
   thing on the page. */

.bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(110, 90, 232, 0.22), transparent 60%),
    var(--g1-base);
}

.bg > i {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(90px);
  will-change: transform;
}

.bg > i:nth-child(1) {
  top: -18%;
  left: -12%;
  width: 46vw;
  height: 46vw;
  background: rgba(110, 90, 232, 0.30);
  animation: drift-a 46s ease-in-out infinite;
}

.bg > i:nth-child(2) {
  right: -16%;
  top: 34%;
  width: 44vw;
  height: 44vw;
  background: rgba(110, 90, 232, 0.16);
  animation: drift-b 54s ease-in-out infinite;
}

.bg > i:nth-child(3) {
  bottom: -14%;
  left: 26%;
  width: 34vw;
  height: 34vw;
  background: rgba(62, 156, 156, 0.10);
  animation: drift-c 40s ease-in-out infinite;
}

.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: overlay;
  background:
    radial-gradient(130% 105% at 50% 42%, transparent 56%, rgba(0, 0, 0, 0.36) 100%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.04 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

@keyframes drift-a {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(7vw, 4vh, 0) scale(1.10); }
}

@keyframes drift-b {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
  50% { transform: translate3d(-8vw, -5vh, 0) scale(0.95); }
}

@keyframes drift-c {
  0%, 100% { transform: translate3d(0, 0, 0) scale(0.96); }
  50% { transform: translate3d(4vw, -6vh, 0) scale(1.06); }
}

/* ===== the one grid ===== */

.wrap {
  position: relative;
  z-index: 2;
  width: min(calc(100% - var(--gutter) * 2), var(--page));
  margin: 0 auto;
}

/* ===== mono chrome =====
   One class, used for every label, file name, URL, index and system string
   on the page. This is the typographic evidence for the OS claim. */

.mono {
  font-family: var(--mono);
  font-size: var(--t--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  font-variant-ligatures: none;
}

/* the eyebrow. It is amber, and amber now appears in a system rather than
   exactly once (finding 15): eyebrows, the sun rule, the struck column
   marker and the payoff caption all use it. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin: 0 0 var(--s-4);
  color: var(--pm-sun);
  text-transform: uppercase;
}

.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(228, 197, 106, 0.45), transparent);
}

.eyebrow.short::after {
  max-width: 96px;
}

/* ===== nav ===== */

.nav {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  -webkit-backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  background: var(--pk-glass-surface, rgba(18, 18, 22, .66));
  border-bottom: 1px solid var(--pk-glass-hairline, rgba(255, 255, 255, .12));
}

.nav .wrap {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  min-width: 0;
}

/* The wordmark yields before the nav links do. On a 360 phone the French
   word for privacy is 115px on its own, and something has to give: it is
   the mark, which is still legible as a glyph. */
.wordmark {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex-shrink: 1;
  min-height: 44px;
  color: var(--ink);
  text-decoration: none;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.03em;
  overflow: hidden;
}

.wordmark .glyph {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 7px;
  background: linear-gradient(160deg, var(--pm-purple-deep), var(--pm-purple));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28);
  display: grid;
  place-items: center;
  color: #fff;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0;
}

.wordmark b {
  display: block;
  font-weight: 700;
  line-height: 1.1;
  white-space: nowrap;
}

.wordmark small {
  display: block;
  margin-top: 1px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.nav-spacer {
  flex: 1;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

.lang {
  display: inline-flex;
  padding: 3px;
  border-radius: var(--pk-radius-control, 10px);
  background: var(--pk-glass-panel, rgba(255, 255, 255, .065));
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, .25));
}

.lang a {
  min-width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  color: var(--ink-2);
  text-decoration: none;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
}

.lang a[aria-current="page"] {
  background: rgba(110, 90, 232, 0.42);
  color: var(--ink);
}

.nav-link {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  flex: none;
  padding: 0 var(--s-3);
  color: var(--ink-2);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

.lang {
  flex: none;
}

.nav-link:hover {
  color: var(--ink);
}

/* ===== hero =====
   The old hero left a 230px dead zone under it with the mockup finishing
   far above the section break (finding 11). The stage is now stretched to
   the column, the hero is not forced to fill the viewport, and the gap
   below is one scale step. */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: var(--s-7);
  align-items: center;
  padding: var(--s-8) 0 var(--s-9);
}

.hero-copy {
  max-width: 34rem;
}

.hero h1 {
  margin: 0 0 var(--s-5);
  font-family: var(--pk-font-display);
  font-size: clamp(1.75rem, 3.4vw, 2.75rem);
  font-synthesis: none;
  line-height: 1.02;
  letter-spacing: -0.025em;
  font-weight: 400;
  color: var(--ink);
  /* text-wrap balance was breaking the headline on a dangling "the"
     (finding 9). The copy carries its own break points instead. */
  text-wrap: pretty;
  hyphens: none;
  -webkit-hyphens: none;
}

/* An explicit break opportunity the copy controls. On one line at desktop
   the H1 breaks where the sentence breaks, not where the balancer decides.

   The word gap lives in the markup as a real space before the span, so it
   is there for a screen reader and for a copy and paste at every width. A
   block level span swallows it visually at desktop, which is the point,
   and at narrow widths the span folds back to inline and the space does
   its normal job. */
.hero h1 .br {
  display: block;
}

.lede {
  margin: 0 0 var(--s-6);
  max-width: var(--measure);
  color: var(--ink-2);
  font-size: var(--t-1);
  line-height: 1.55;
}

html:not(.is-ready):not(.no-js) .swap {
  opacity: 0;
}

html.is-ready .swap,
html.no-js .swap {
  opacity: 1;
  transition: opacity 180ms var(--ease);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4) var(--s-5);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 50px;
  padding: 0 var(--s-5);
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, .25));
  border-radius: var(--pk-radius-control, 10px);
  background: var(--pk-accent, #5956E9);
  color: #fff;
  font-family: var(--font);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: none;
  box-shadow: var(--pk-glass-shadow, 0 10px 28px rgba(12, 10, 18, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.20));
  cursor: pointer;
  transition: background 140ms var(--ease), transform 140ms var(--ease);
}

.btn:hover {
  background: var(--pm-purple-deep);
  color: #FFFFFF;
  transform: translateY(-1px);
}

.btn svg {
  display: none;
}

.btn:hover svg {
  transform: translateX(3px);
}

/* The secondary action had no underline, no arrow, no border and no hover
   cue, so it read as body text next to a button (finding 20). It is now an
   underlined mono link with a caret and a real hover state. */
/* An inline box, not a flex row. A flex row puts the caret on its own axis
   and strands it at the far edge when the label wraps, which the longer
   French label does on a phone. Inline keeps the caret welded to the last
   word wherever that word ends up. */
.ghost {
  display: inline-block;
  min-height: 50px;
  padding: 14px var(--s-1);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.04em;
  text-decoration: underline;
  text-decoration-color: var(--line-3);
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  transition: color 140ms var(--ease), text-decoration-color 140ms var(--ease);
}

/* The shared Font Awesome helper decorates every a[data-os], and the ghost is
   one, so once action-icons.js has run this element carries a real trailing
   arrow glyph. The CSS caret below then paints a SECOND mark after it: a
   1440 capture showed an arrow and a chevron side by side. The caret is kept
   only for the pre-script and no-JS frame, where the glyph does not exist,
   and stands down the moment the helper claims the element. */
.ghost[data-pk-action]::after {
  content: none;
}

/* The trailing Font Awesome glyph must stay welded to the last word. The
   glyph is a separate inline element, so the space before it is a wrap
   opportunity: at 375 the longer French label filled the line and the arrow
   alone dropped to a second row, pointing at nothing.

   Measured at 375, 390 and 360 before choosing: zeroing the glyph margin
   fixes the wrap but welds the arrow to the last letter, and a word joiner
   alone does not fix it at all. The space this element actually needs comes
   from its own inline padding, which is decorative here because .ghost is an
   underlined link rather than a filled control. Reclaiming it keeps the
   normal .55em gap before the arrow AND keeps arrow and last word on one
   line. The vertical padding stays, so the 44px touch target is unchanged. */
.ghost[data-pk-action] {
  padding-inline: 0;
}

.ghost::after {
  content: "";
  display: inline-block;
  vertical-align: middle;
  margin: -2px 0 0 var(--s-2);
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-top: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 160ms var(--ease);
}

.ghost:hover {
  color: var(--pm-lavender);
  text-decoration-color: var(--pm-lavender);
}

.ghost:hover::after {
  transform: rotate(45deg) translate(2px, -2px);
}

.fine {
  margin: var(--s-5) 0 0;
  max-width: var(--measure);
  color: var(--ink-3);
  font-size: 14px;
  line-height: 1.55;
}

/* ===== the mockup =====
   The old stage clipped a pill in half at an arbitrary point (finding 1)
   because .os was 672px wide inside a 579px .stage with overflow hidden.
   The stage now sizes the OS, so nothing is guillotined. */

.stage-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.stage {
  position: relative;
  isolation: isolate;
  border-radius: var(--r-sheet);
}

/* The glow used to spill 4 percent past the stage on each side, which put
   6px of horizontal scroll on the document at 1024. It now stays inside
   its own box and gets its spread from blur instead of from geometry. */
.stage-glow {
  position: absolute;
  inset: 6% 0 auto;
  height: 72%;
  z-index: 0;
  background: radial-gradient(closest-side, rgba(110, 90, 232, 0.38), transparent 74%);
  filter: blur(18px);
  pointer-events: none;
}

.os {
  position: relative;
  z-index: 1;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--r-sheet);
  overflow: hidden;
  background: #0B0911;
  border: 1px solid var(--line-3);
  box-shadow:
    0 30px 70px rgba(0, 0, 0, 0.55),
    0 2px 8px rgba(0, 0, 0, 0.34),
    inset 0 1px 0 rgba(255, 255, 255, 0.20);
  /* the mockup drives its own type off one number so every part of it
     scales together and no label is ever cut for want of room */
  container-type: inline-size;
  font-size: clamp(9px, 1.55cqi, 13px);
}

.os-wall {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(110, 90, 232, 0.34), transparent 58%),
    #08060F;
}

.os-wall > i {
  position: absolute;
  border-radius: 50%;
  filter: blur(44px);
}

.os-wall > i:nth-child(1) {
  top: -20%;
  left: -8%;
  width: 46%;
  height: 58%;
  background: rgba(130, 115, 255, 0.44);
}

.os-wall > i:nth-child(2) {
  right: -10%;
  bottom: -24%;
  width: 50%;
  height: 62%;
  background: rgba(110, 90, 232, 0.40);
}

.os-wall > i:nth-child(3) {
  top: 24%;
  right: 18%;
  width: 28%;
  height: 32%;
  background: rgba(169, 155, 255, 0.24);
}

.os-halo {
  position: absolute;
  top: 3.2%;
  right: 2.6%;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 0.9em;
  padding: 0.5em 1em;
  border-radius: 999px;
  background: rgba(20, 16, 30, 0.86);
  border: 1px solid var(--line-3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.92em;
  font-weight: 500;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.os-halo .sep {
  width: 1px;
  height: 1.1em;
  background: var(--line-2);
}

.os-halo .time {
  font-variant-numeric: tabular-nums;
}

/* One column, not two. The second column was what the window landed on,
   and it is what forced the long file name into a 2 line clamp that cut it
   mid word. One column at the full label width means the hot file name,
   which is the whole point of the shot, reads in full. */
.os-icons {
  position: absolute;
  top: 11%;
  left: 3.2%;
  width: 26%;
  z-index: 3;
  display: grid;
  gap: 0.6em;
}

.icon {
  display: grid;
  grid-template-columns: 2.6em minmax(0, 1fr);
  align-items: center;
  gap: 0.6em;
  padding: 0.4em 0.5em;
  border-radius: 0.7em;
}

.icon.hot {
  background: rgba(110, 90, 232, 0.28);
  outline: 1px solid rgba(169, 155, 255, 0.55);
}

.icon .well {
  width: 2.6em;
  height: 2.6em;
  border-radius: 0.72em;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05));
  border: 1px solid var(--line-2);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.24);
}

.icon.plum .well { background: linear-gradient(180deg, #8A7AF0, #5A48C8); }
.icon.sun .well { background: linear-gradient(180deg, #F0D78A, #C9A44A); }
.icon.teal .well { background: linear-gradient(180deg, #5BB8B8, #2A6B6B); }
.icon.paper .well { background: linear-gradient(180deg, #ECE8F6, #B7B3C4); }

.icon span {
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.74em;
  font-weight: 500;
  line-height: 1.25;
  text-shadow: 0 1px 3px rgba(12, 10, 18, 0.95);
  overflow-wrap: anywhere;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

/* The window was the same value as the desktop with no scrim, no blur that
   read, and it sat on top of the icon grid truncating labels, so the
   overlap looked like a z index accident (finding 2). It now has a real
   backplate, a real blur and a real shadow, and it clears the icon column
   entirely. */

/* The backplate that makes the window read as layered rather than as a z
   index accident. It dims the desk enough to separate the two planes and
   not so much that the desk stops being a desk. */
.os-scrim {
  position: absolute;
  inset: 0;
  z-index: 4;
  background: rgba(6, 4, 12, 0.42);
  pointer-events: none;
}

.os-window {
  position: absolute;
  z-index: 5;
  left: 31%;
  top: 15%;
  width: 62%;
  height: 62%;
  border-radius: var(--pk-radius-window, 24px);
  background: var(--pk-glass-surface, rgba(18, 18, 22, .66));
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, .25));
  box-shadow: var(--pk-glass-shadow);
  backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  -webkit-backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.titbar {
  position: relative;
  height: 2.9em;
  flex: none;
  display: flex;
  align-items: center;
  padding: 0 1em;
  background: rgba(255, 255, 255, 0.05);
  border-bottom: 1px solid var(--line);
}

.wbtg {
  width: 0.85em;
  height: 0.85em;
  border-radius: 4px;
  margin-right: 0.55em;
  flex: none;
}

.wbtg.plum { background: var(--pm-purple-deep); }
.wbtg.sun { background: var(--pm-sun); }
.wbtg.teal { background: var(--pm-teal-bright); }

.titbar p {
  position: absolute;
  left: 6em;
  right: 6em;
  margin: 0;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.86em;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

.app {
  flex: 1;
  padding: 1.15em 1.35em 1.35em;
  overflow: hidden;
}

.app-panel {
  display: none;
  height: 100%;
}

.os[data-shot="desk"] [data-panel="desk"],
.os[data-shot="table"] [data-panel="table"],
.os[data-shot="roast"] [data-panel="roast"],
.os[data-shot="speed"] [data-panel="speed"],
.os[data-shot="compare"] [data-panel="compare"],
.os[data-shot="welcome"] [data-panel="welcome"],
.os[data-shot="form"] [data-panel="form"],
.os[data-shot="note"] [data-panel="note"],
.os[data-shot="doors"] [data-panel="doors"],
.os[data-shot="listings"] [data-panel="listings"],
.os[data-shot="phone"] [data-panel="phone"],
.os[data-shot="ads"] [data-panel="ads"] {
  display: flex;
  flex-direction: column;
  gap: 0.8em;
}

/* A drawing of a window title, not a document heading. The mockup is
   aria-hidden, and a picture of a heading is still not a heading, so it is
   marked up as what it is. */
.app .app-title {
  margin: 0;
  color: var(--ink);
  font-size: 1.22em;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.25;
}

.app p {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.95em;
  line-height: 1.45;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.45em;
}

.field span:first-child {
  font-family: var(--mono);
  font-size: 0.8em;
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--ink-2);
}

.fake-input {
  height: 3em;
  display: flex;
  align-items: center;
  padding: 0 0.9em;
  border-radius: var(--r-btn);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--line-2);
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 0.95em;
}

.fake-btn {
  align-self: flex-start;
  height: 2.7em;
  padding: 0 1.1em;
  border-radius: var(--r-btn);
  background: var(--pm-purple);
  color: #fff;
  font-size: 0.95em;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45em;
}

.chip {
  height: 2.3em;
  padding: 0 0.8em;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  font-size: 0.88em;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.chip.on {
  background: rgba(110, 90, 232, 0.34);
  border-color: rgba(169, 155, 255, 0.48);
}

.note-body {
  flex: 1;
  padding: 0.6em 0;
  color: var(--ink-2);
  font-size: 0.95em;
  line-height: 1.5;
  border-top: 1px solid var(--line);
}

.dead {
  height: 2.7em;
  border-radius: var(--r-btn);
  border: 1px dashed var(--line-2);
  color: var(--ink-3);
  display: grid;
  place-items: center;
  font-size: 0.9em;
  font-weight: 700;
}

.phone-frame {
  width: 7em;
  height: 11.5em;
  margin: 0 auto;
  border-radius: 1.2em;
  background: #141018;
  border: 2px solid rgba(255, 255, 255, 0.2);
  padding: 0.8em 0.6em;
  display: flex;
  flex-direction: column;
  gap: 0.4em;
}

.phone-frame b,
.phone-frame i {
  display: block;
  height: 0.6em;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.18);
}

.phone-frame b { width: 78%; }
.phone-frame i { width: 100%; height: 0.45em; }

.ads-card {
  flex: 1;
  border-radius: 8px;
  background:
    linear-gradient(180deg, rgba(42, 107, 107, 0.35), rgba(20, 16, 24, 0.2)),
    repeating-linear-gradient(-18deg, transparent, transparent 8px, rgba(255, 255, 255, 0.03) 8px, rgba(255, 255, 255, 0.03) 9px);
  display: grid;
  place-items: end start;
  padding: 0.9em;
}

.ads-card span {
  font-size: 0.9em;
  font-weight: 700;
  color: var(--ink);
  background: rgba(12, 10, 18, 0.75);
  padding: 0.3em 0.6em;
  border-radius: 4px;
}

/* Four empty placeholder squares shipped as final in the one screenshot
   whose job is to sell a real product (finding 3). The real dock icons
   exist and are now in it. */

.os-dock {
  position: absolute;
  left: 50%;
  bottom: 2.6%;
  z-index: 6;
  transform: translateX(-50%);
  padding: 0.45em 0.6em;
  display: flex;
  align-items: center;
  gap: 0.5em;
  border-radius: var(--r-dock);
  background: var(--pk-glass-surface, rgba(18, 18, 22, .66));
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, .25));
  box-shadow: var(--pk-glass-shadow);
  backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  -webkit-backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
}

.tile {
  width: 2.9em;
  height: 2.9em;
  border-radius: 0.75em;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.tile img {
  width: 100%;
  height: 100%;
  display: block;
}

.tile.mark {
  width: auto;
  padding: 0 0.75em;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.82em;
  font-weight: 700;
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid var(--line-2);
}

/* ===== sections =====
   One rhythm: s-9 top, s-9 bottom, everywhere. The hairline is the only
   divider, so the page reads as a continuous surface with measured stops
   rather than as a stack of unrelated slabs. */

.band {
  padding: var(--s-9) 0;
}

.band + .band,
.section-line {
  border-top: 1px solid var(--line);
}

/* The payoff is the loudest thing on the page and gets a wider frame to
   sit in, so the eye registers a change of gear at the one moment the page
   stops explaining and starts showing. */
.band.is-feature {
  --page: 1280px;
}

.sec-head {
  margin: 0 0 var(--s-7);
}

/* Headings get their own measure. A display size held to a body measure
   wraps where the sentence does not want to break. */
.sec-head h2 {
  margin: 0;
  max-width: 22ch;
  font-size: clamp(1.75rem, 3vw, var(--t-4));
  line-height: 1.12;
  letter-spacing: -0.035em;
  font-weight: 700;
  text-wrap: balance;
}

.sec-head p {
  margin: var(--s-4) 0 0;
  /* ch is relative to the element's own font, and this one is a step above
     body, so the cap has to be in the same currency as the body measure it
     is meant to match. 62ch of body text at 16px is 50ch here at 20px. */
  max-width: 50ch;
  color: var(--ink-2);
  font-size: var(--t-1);
  line-height: 1.55;
}

/* ===== how it works =====
   The cards were a 6 percent lift with an 8 percent border, ghost numerals
   floating between cap height and baseline, and a 2 point title to body
   difference (findings 6, 7, 13, 14). Now: a real surface, a mono index
   chip on the baseline grid, and content aligned to the top with the card
   height driven by content rather than a min-height. */

/* Cards are top aligned and sized by their own copy, not stretched to a
   common height. Stretching gave card one 26px more bottom air than card
   three for no reason a reader could see, which is the ragged interior the
   review found. The grid keeps the tops on one line, which is the alignment
   that actually reads. */
.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-5);
  align-items: start;
}

.step {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--s-6);
  border-radius: var(--r-sheet);
  background: var(--card);
  border: 1px solid var(--card-line);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset, 0 20px 44px rgba(0, 0, 0, 0.30);
}

/* No hover state on these cards on purpose. They are not links, and a lift
   on hover would promise a destination the page does not have. The single
   primary action stays single. */

.step .n {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  margin: 0 0 var(--s-5);
  flex: none;
  border-radius: 8px;
  background: rgba(110, 90, 232, 0.22);
  border: 1px solid rgba(169, 155, 255, 0.34);
  color: var(--pm-lavender);
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.step h3 {
  margin: 0 0 var(--s-3);
  font-size: var(--t-2);
  line-height: 1.2;
  letter-spacing: -0.025em;
  font-weight: 700;
}

.step p {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--t-0);
  line-height: 1.6;
}

/* ===== what this is not =====
   A huge empty left column, an orphan eyebrow and four punchy fragments
   crammed into one grey paragraph (finding 18). The fragments were always
   a list. Now they are one: struck on the left, checked on the right. */

.not-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
}

.not-col {
  padding: var(--s-6);
  border-radius: var(--r-sheet);
  background: var(--card);
  border: 1px solid var(--card-line);
}

.not-col.is-yes {
  background: var(--card-2);
  border-color: rgba(169, 155, 255, 0.30);
}

.not-col > h3 {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin: 0 0 var(--s-5);
  font-family: var(--mono);
  font-size: var(--t--1);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.not-col.is-yes > h3 {
  color: var(--pm-sun);
}

.not-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.not-list li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: start;
  font-size: var(--t-0);
  line-height: 1.5;
}

.not-list .mk {
  margin-top: 2px;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  flex: none;
}

.is-no .mk {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--line-2);
  color: var(--ink-3);
}

.is-yes .mk {
  background: rgba(228, 197, 106, 0.14);
  border: 1px solid rgba(228, 197, 106, 0.40);
  color: var(--pm-sun);
}

.not-list .mk svg {
  width: 12px;
  height: 12px;
}

.is-no .not-list span:last-child {
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-color: rgba(255, 255, 255, 0.34);
  text-decoration-thickness: 1px;
}

.is-yes .not-list span:last-child {
  color: var(--ink);
}

/* ===== the payoff =====
   The page promised "the next screen is the joke" and never showed the joke
   (finding 22). These are real captures of the shipped OS, not mockups. */

/* The swarm frame runs the full column: it is the one screenshot that makes
   this page memorable and a thumbnail wastes it. The rest card sits below
   at half width, paired with the line that explains the landing. */
.payoff-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: stretch;
}

.payoff-grid .frame.wide {
  grid-column: 1 / -1;
}

/* the paired frame and note share a row, so the frame gives its caption the
   leftover height rather than leaving a ragged bottom next to the note */
.payoff-grid .frame {
  display: flex;
  flex-direction: column;
}

.payoff-grid .frame figcaption {
  flex: 1;
}

.payoff-note {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s-4);
  padding: var(--s-6);
  border-radius: var(--r-sheet);
  background: var(--card-2);
  border: 1px solid var(--card-line);
}

.payoff-note h3 {
  margin: 0;
  font-size: var(--t-2);
  line-height: 1.2;
  letter-spacing: -0.025em;
}

.payoff-note p {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--t-0);
  line-height: 1.6;
}

.frame {
  margin: 0;
  border-radius: var(--r-sheet);
  background: var(--card);
  border: 1px solid var(--card-line);
  overflow: hidden;
  box-shadow: 0 24px 56px rgba(0, 0, 0, 0.36);
}

.frame img {
  display: block;
  width: 100%;
  height: auto;
  border-bottom: 1px solid var(--line);
}

.frame figcaption {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5) var(--s-5);
  color: var(--ink-2);
  font-size: 15px;
  line-height: 1.5;
}

.frame figcaption b {
  flex: none;
  color: var(--pm-sun);
  font-family: var(--mono);
  font-size: var(--t--1);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ===== proof =====
   A lone centred sentence in a left aligned page with a 15px grey line
   holding the only specific number on it (finding 19). 29 is real and it
   stays 29. Nothing here is invented: no logos we do not have, no
   testimonial, no rating, no availability. */

.proof-strip {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 var(--s-7);
  align-items: center;
  padding: var(--s-7);
  border-radius: var(--r-sheet);
  background:
    radial-gradient(70% 140% at 0% 50%, rgba(110, 90, 232, 0.16), transparent 70%),
    var(--card);
  border: 1px solid var(--card-line);
  overflow: hidden;
}

/* the amber rule that ties this strip to the eyebrow system */
.proof-strip::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: linear-gradient(180deg, var(--pm-sun), rgba(228, 197, 106, 0.12));
}

.proof-num {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin: 0;
  padding-right: var(--s-7);
  border-right: 1px solid var(--card-line);
  font-size: clamp(3.4rem, 6vw, 5rem);
  line-height: 0.86;
  letter-spacing: -0.055em;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.proof-num i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--pm-sun);
  box-shadow: 0 0 0 4px rgba(228, 197, 106, 0.16);
  flex: none;
  align-self: center;
}

.proof-body p {
  margin: 0;
  max-width: 44ch;
  color: var(--ink-2);
  font-size: var(--t-0);
  line-height: 1.55;
}

.proof-body p + p {
  margin-top: var(--s-2);
}

.proof-body a {
  display: inline-block;
  padding: 2px 0;
  color: var(--ink);
  font-weight: 700;
  text-decoration-color: var(--line-3);
}

.proof-body a:hover {
  color: var(--pm-lavender);
}

/* ===== closing call ===== */

.repeat {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
  padding: var(--s-9) 0;
  border-top: 1px solid var(--line);
}

.repeat-copy {
  max-width: 30rem;
}

.repeat h2 {
  margin: 0;
  font-size: clamp(1.75rem, 3vw, var(--t-4));
  line-height: 1.12;
  letter-spacing: -0.035em;
}

.repeat p {
  margin: var(--s-3) 0 0;
  color: var(--ink-2);
  font-size: var(--t-0);
}

.repeat-act {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
}

/* ===== footer =====
   Ungrouped links, phone as plain text, no columns, no structure, and a low
   resolution raster logo whose blue was off brand (findings 17 and 21).
   Now: a vector mark traced from the real artwork, three labelled groups,
   and the phone as a real link. */

.foot {
  padding: var(--s-8) 0 var(--s-7);
  border-top: 1px solid var(--line);
  background: rgba(9, 7, 14, 0.55);
}

.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 0.9fr));
  gap: var(--s-7) var(--s-6);
}

.foot-brand img {
  width: 148px;
  height: auto;
  display: block;
}

.foot-brand p {
  margin: var(--s-4) 0 0;
  max-width: 30ch;
  color: var(--ink-2);
  font-size: 14px;
  line-height: 1.6;
}

.foot-col h2 {
  margin: 0 0 var(--s-4);
  font-family: var(--mono);
  font-size: var(--t--1);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.foot-col ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.foot-col a,
.foot-col span {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink-2);
  text-decoration: none;
  font-size: 15px;
}

.foot-col a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line-3);
}

.foot-col .tel {
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--ink);
  font-weight: 500;
}

.foot-base {
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  align-items: center;
  justify-content: space-between;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.04em;
}

/* ===== embed ===== */

html.is-embed .nav {
  position: static;
}

html.is-embed .hero {
  padding: var(--s-6) 0 var(--s-7);
}

html.is-embed .band,
html.is-embed .repeat {
  padding-top: var(--s-7);
  padding-bottom: var(--s-7);
}

/* ===== preferences ===== */

@media (prefers-reduced-motion: reduce) {
  .bg > i {
    animation: none !important;
  }
  html.is-ready .swap {
    transition: none;
  }
  .btn,
  .btn svg,
  .ghost,
  .ghost::after {
    transition: none;
  }
  .btn:hover {
    transform: none;
  }
}

@media (prefers-reduced-transparency: reduce) {
  :root {
    --g2-a: 0.96;
    --g3-a: 0.98;
  }
  .nav,
  .os-window,
  .os-dock {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: #16121F;
  }
}

@media (prefers-contrast: more) {
  :root {
    --ink-2: #DEDCE6;
    --ink-3: #C8C4D4;
    --card-line: rgba(255, 255, 255, 0.28);
    --card-line-2: rgba(255, 255, 255, 0.38);
  }
}

/* ===== responsive =====
   The container and the gutter are the same at every width. Only the number
   of columns changes. */

@media (max-width: 1080px) {
  .hero {
    grid-template-columns: 1fr;
    gap: var(--s-7);
    padding: var(--s-7) 0 var(--s-8);
  }
  .hero-copy {
    max-width: none;
  }
  .hero h1 .br {
    display: inline;
  }
  .payoff-grid {
    grid-template-columns: 1fr;
  }
  .foot-grid {
    grid-template-columns: minmax(0, 1.2fr) repeat(2, minmax(0, 1fr));
  }
  .foot-brand {
    grid-column: 1 / -1;
  }
}

@media (max-width: 900px) {
  .steps {
    grid-template-columns: 1fr;
  }
  .not-grid {
    grid-template-columns: 1fr;
  }
  .proof-strip {
    grid-template-columns: 1fr;
    gap: var(--s-4);
    padding: var(--s-6);
  }
  .proof-num {
    padding: 0 0 var(--s-4);
    border-right: 0;
    border-bottom: 1px solid var(--card-line);
  }
  .os-icons {
    display: none;
  }
  .os-window {
    left: 7%;
    width: 86%;
  }
}

@media (max-width: 640px) {
  :root {
    --gutter: 20px;
  }
  .band,
  .repeat {
    padding: var(--s-8) 0;
  }
  .lede {
    font-size: 17px;
  }
  .step,
  .not-col {
    padding: var(--s-5);
  }
  /* On a phone the mockup has no icon column to make room for, so the
     window takes the frame and gets a taller box. The FR copy is the long
     one and it is what this is sized against. */
  /* The frame is sized by what is in it: title bar, panel, dock, and the
     air between them. Nothing here is a fixed fraction of a guessed box. */
  .os {
    aspect-ratio: auto;
    min-height: 0;
    /* dock height plus its offset plus a clear gap above it */
    padding: 0 0 6.4em;
    font-size: clamp(10px, 3.1cqi, 13px);
  }
  /* On a phone the window is sized by its copy, not by a fixed fraction of
     the frame. FR runs two lines longer than EN in this panel, and a fixed
     height either clipped one or left a lake of empty glass under the
     other. Height auto with the panel at natural height fits both. */
  .os-window {
    position: relative;
    left: auto;
    right: auto;
    top: auto;
    margin: 3.4em 6% 0;
    width: auto;
    height: auto;
  }
  .os-halo {
    top: 1em;
    right: 1em;
  }
  .app {
    flex: none;
  }
  .app-panel {
    height: auto;
  }
  .cta-row {
    gap: var(--s-3);
    align-items: stretch;
    flex-direction: column;
  }
  .cta-row .btn {
    width: 100%;
  }
  .ghost {
    text-align: center;
    /* the French label is the long one; at 12px it holds one line at 390 */
    font-size: 12px;
    letter-spacing: 0.02em;
  }
  .foot-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-6) var(--s-5);
  }
  .foot-base {
    justify-content: flex-start;
  }
  .repeat-act {
    width: 100%;
  }
  .repeat-act .btn {
    width: 100%;
  }
}

@media (max-width: 420px) {
  .foot-grid {
    grid-template-columns: 1fr;
  }
  .wordmark small {
    display: none;
  }
  .nav-link {
    padding: 0 var(--s-2);
  }
  /* At the narrowest phones the French word for privacy is wider than the
     room left beside the language switch. Earlier rounds solved that by
     truncating the brand to "Pekan ..." and then hiding it outright below
     380, which trades one product's name for another's punctuation: the
     visitor loses the only thing on the header that says whose desktop this
     is.

     The row is a flex line with a spacer, so the fix is to stop making the
     brand pay for the whole overflow. The gap and the nav padding tighten,
     the brand keeps its full text, and nothing is clipped or removed. */
  .wordmark {
    gap: 7px;
  }
  .wordmark b {
    font-size: 15px;
    white-space: nowrap;
  }
}

@media (max-width: 400px) {
  /* Below 400 the three items need real room, and they get it from the
     spacing rather than from any one of them being shortened or dropped.
     Measured after this rule at 390, 375 and 360: the brand renders its
     full text unclipped, the switcher keeps both languages, and the privacy
     link keeps the whole word Confidentialite with its accent. */
  .site-head .wrap {
    gap: 8px;
  }
  .nav-links {
    gap: 6px;
  }
  .nav-link {
    padding: 0 6px;
    font-size: 13px;
  }
  .lang {
    padding: 2px;
  }
  .lang a {
    padding: 0 9px;
  }
}

/* Owner typography: descriptive sections have a distinct subtitle voice. */
.sec-head h2, .step h3, .payoff-note h3, .repeat h2 {
  font-family: var(--pk-font-subtitle); font-weight: 500;
  font-variation-settings: "wdth" 100, "YOPQ" 100;
}
