/* Xpurge site.

   A flat poster idiom: warm paper, full-bleed blocks of saturated colour,
   chunky uppercase display type, and hard offset shadows instead of soft
   blur. No gradients anywhere.

   Two details carry the look. First, the hard shadow: a control is a filled
   shape with a 1px border one shade darker than its fill and a solid
   `0 3px 0` shadow in that same shade, so it reads as a tile sitting proud of
   the page. Second, the bands: each section owns the full width in one flat
   colour, and they alternate, so the page reads as stacked blocks rather than
   as cards floating on white.

   Palette and type match the extension. If you change a token here, change it
   in xpurge-extension/src/ui/styles.css too.

   Fonts are self-hosted rather than fetched from Google, so the page makes no
   third-party request. */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Archivo Black';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/archivo-black-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light;

  --ink: #17140f;
  --paper: #faf6ef;
  --surface: #fffdf8;
  --sunken: #f2ebdd;
  --border: #e3d8c5;
  --border-strong: #c9baa1;
  /* Both carry real content (the hero note, the per-day price, the
     comparison table), so both clear WCAG AA 4.5:1 on the worst surface they
     sit on — sunken in light, surface in dark. */
  --muted: #5f574b;
  --faint: #70675b;

  --ember: #c7391a;
  --ember-edge: #97290f;
  --ember-soft: #fbe9e3;
  --butter: #f5ce63;
  --butter-edge: #bd952c;
  --butter-ink: #5e4a12;
  --clay: #efb79b;
  --clay-edge: #c1876a;
  --clay-ink: #5c3524;
  --charcoal: #211d18;

  --ok: #2f7d4f;

  --radius: 12px;
  --radius-sm: 9px;
  --font: 'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-display: 'Archivo Black', 'Archivo', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

  --measure: 34rem;
  --gutter: clamp(1.25rem, 5vw, 2.5rem);

  /* Motion. `--bounce` overshoots past its endpoint and settles back, which
     is what reads as weight rather than as a fade. Everything that moves uses
     these two so the whole page shares one sense of physics. */
  --bounce: cubic-bezier(.34, 1.56, .64, 1);
  --bounce-soft: cubic-bezier(.22, 1.2, .36, 1);
  --bounce-fast: 180ms;
  --bounce-hover: 260ms;
  --bounce-slow: 420ms;
}

/* Dark mode keeps the coloured bands exactly as they are — butter and clay
   are brand blocks, not surfaces, and they carry dark text in both themes.
   Only the paper and the cards that sit on it change. */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --ink: #f5efe4;
    --paper: #17140f;
    --surface: #221d17;
    --sunken: #1c1813;
    --border: #352e25;
    --border-strong: #4d4235;
    --muted: #b3a695;
    --faint: #918473;
    --ember: #f0673f;
    --ember-edge: #9c3a1e;
    --ember-soft: #2e1a13;
    --charcoal: #0e0c09;
  }
}

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 16px/1.6 var(--font);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; }
[hidden] { display: none !important; }

a { color: var(--ember); text-underline-offset: 3px; }

h1, h2, h3 { margin: 0; }

/* The display face is always uppercase and always tight. Its job is to be
   loud; letting it set at a normal line-height wastes the effect. */
h1, h2 {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: .95;
  letter-spacing: -.02em;
}
h1 { font-size: clamp(2.6rem, 8vw, 5rem); }
h2 { font-size: clamp(1.75rem, 4.5vw, 2.75rem); }
h3 { font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; line-height: 1.3; }
p { margin: 0; }

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

/* --- bands -------------------------------------------------------------- */
/* Full-bleed colour blocks. Each sets its own text colours so anything
   inside inherits the right contrast without knowing which band it is in. */

.band { padding-block: clamp(3rem, 8vw, 5.5rem); }
.band.paper { background: var(--paper); }
.band.sunken { background: var(--sunken); }
/* Butter and clay are brand blocks: they are the same light colour in both
   themes. So everything inside them has to be pinned to the light palette,
   not inherited from the theme — in dark mode the cards were coming out
   near-black on yellow with dark-brown body text on top of that. */
.band.butter, .band.clay {
  color: #17140f;
  --ink: #17140f;
  --surface: #fffdf8;
  --sunken: #f2ebdd;
  --border: #e3d8c5;
  --border-strong: #c9baa1;
  --ember: #c7391a;
  --ember-edge: #97290f;
  --ok: #2f7d4f;
}
.band.butter { background: var(--butter); --muted: var(--butter-ink); --faint: var(--butter-ink); }
.band.clay { background: var(--clay); --muted: var(--clay-ink); --faint: var(--clay-ink); }
.band.dark {
  background: var(--charcoal);
  color: #f5efe4;
  --muted: #c2b6a4;
  --faint: #a1968a;
  --surface: #2c2720;
  --border: #3b352c;
  --border-strong: #52493c;
}

.band > .wrap > h2 + p.lead { margin-top: 1rem; color: var(--muted); max-width: var(--measure); font-size: 1.05rem; }

/* The wavy divider between bands. The SVG inherits `color`, so the wrapper
   is given the colour of the band it is flowing into. */
.wave { display: block; line-height: 0; }
/* The divider SVG paints with currentColor, so the class names the band it
   is flowing into. Kept as classes rather than inline styles so the site can
   ship a strict CSP with no unsafe-inline. */
.wave.to-butter { color: var(--butter); }
.wave.to-clay { color: var(--clay); }
.wave.to-paper { color: var(--paper); }
.wave.to-charcoal { color: var(--charcoal); }
.wave svg { display: block; width: 100%; height: clamp(20px, 3vw, 38px); }

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

.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1.1rem;
  flex-wrap: wrap;
}

.mark {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-family: var(--font-display);
  font-size: 1.3rem;
  text-transform: uppercase;
  letter-spacing: -.02em;
  text-decoration: none;
  color: inherit;
}
.mark img { width: 30px; height: 30px; display: block; border-radius: 8px; }

.top nav {
  display: flex;
  gap: 1.35rem;
  align-items: center;
  font-size: .95rem;
  font-weight: 600;
  flex-wrap: wrap;
}
.top nav a { color: var(--muted); text-decoration: none; }
.top nav a:hover { color: var(--ink); }
.top nav a.btn { color: var(--ink); }

/* --- buttons ------------------------------------------------------------ */

/* Each variant sets its own --edge; the shared rules below then read it, so
   the three states stay in step without repeating a colour three times. */
.btn {
  --edge: var(--border-strong);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .75rem 1.3rem;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 700;
  font-size: .97rem;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 3px 0 0 var(--edge);
  transition: transform var(--bounce-fast) var(--bounce), box-shadow var(--bounce-fast) var(--bounce), background-color .15s linear;
}

/* The shadow is the affordance: the tile rises off the page under the cursor
   and is driven flat into it on press. Hover overshoots slightly and settles;
   the press is deliberately quick and linear, because a bouncy press feels
   mushy rather than clicky. */
.btn:hover { transform: translateY(-2px); box-shadow: 0 7px 0 0 var(--edge); }
.btn:active {
  transform: translateY(3px);
  box-shadow: 0 0 0 0 var(--edge);
  transition-duration: 60ms;
  transition-timing-function: ease-out;
}
.btn:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; }

.btn.primary { --edge: var(--butter-edge); background: var(--butter); color: #17140f; }
.btn.primary:hover { background: #f7d67c; }

.btn.ember { --edge: var(--ember-edge); background: var(--ember); color: #fff; }
.btn.ember:hover { background: #d64420; }

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

.hero { padding-block: clamp(2.5rem, 7vw, 4.5rem) clamp(3rem, 8vw, 5rem); }
.hero h1 { max-width: 16ch; }

/* The marker highlight behind a phrase.

   `box-decoration-break: clone` is what makes this work: the phrase stays
   inline, so each wrapped line gets its own highlight hugging its own text.
   An inline-block with a positioned pseudo-element looked right on one line
   and became a single full-width slab as soon as the phrase wrapped.

   The fill is butter in both themes, so the text on it is always ink — the
   inherited cream would be illegible on yellow. */
.hl {
  background: var(--butter);
  color: #17140f;
  padding: .02em .14em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.hero p.lead {
  margin-top: 1.4rem;
  font-size: clamp(1.05rem, 2.2vw, 1.25rem);
  color: var(--muted);
  max-width: var(--measure);
}
.actions { display: flex; gap: .8rem; margin-top: 2rem; flex-wrap: wrap; }
.hero .note { margin-top: 1.1rem; font-size: .88rem; color: var(--faint); }

/* --- cards -------------------------------------------------------------- */

.grid {
  display: grid;
  gap: 1rem;
  margin-top: 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.card {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 1.4rem;
  box-shadow: 0 3px 0 0 var(--border-strong);
  transition: transform var(--bounce-hover) var(--bounce), box-shadow var(--bounce-hover) var(--bounce);
}
.card h3 { margin-bottom: .5rem; }
.card p { color: var(--muted); font-size: .95rem; }

/* Hovering a card lifts it and deepens its shadow.
   The shadow has to grow by MORE than the card lifts, or the two cancel out:
   at -6px lift with a 3px->9px shadow the outer edge sits at +3 in both states,
   the gap simply fills in, and a perfectly good 420ms transition looks instant.
   Lifting 4 while the shadow goes to 10 moves that edge from +3 to +6, so the
   growth is actually visible. */
@media (hover: hover) {
  .card:hover { transform: translateY(-4px); box-shadow: 0 10px 0 0 var(--border-strong); }
}

/* A small square tile holding an icon or a step number, borrowed from the
   feature rows: bordered, flat fill, same hard edge as everything else. */
.tile {
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  background: var(--butter);
  border: 1px solid var(--butter-edge);
  color: #17140f;
  font-family: var(--font-display);
  font-size: .95rem;
  margin-bottom: .9rem;
}

/* --- pricing ------------------------------------------------------------ */

.plans {
  display: grid;
  gap: 1rem;
  margin-top: 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(13.5rem, 1fr));
}

.plan {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 1.6rem 1.35rem 1.35rem;
  text-align: center;
  box-shadow: 0 3px 0 0 var(--border-strong);
  display: flex;
  flex-direction: column;
  gap: .25rem;
  transition: transform var(--bounce-hover) var(--bounce), box-shadow var(--bounce-hover) var(--bounce);
}
@media (hover: hover) {
  .plan:hover { transform: translateY(-4px); box-shadow: 0 10px 0 0 var(--border-strong); }
  .plan.best:hover { box-shadow: 0 10px 0 0 var(--butter-edge); }
}
.plan.best {
  background: var(--butter);
  border-color: var(--butter-edge);
  color: #17140f;
  box-shadow: 0 3px 0 0 var(--butter-edge);
}
.plan .term {
  font-size: .82rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 700;
  color: var(--muted);
}
.plan.best .term { color: var(--butter-ink); }
.plan .price {
  font-family: var(--font-display);
  font-size: 2.6rem;
  line-height: 1;
  letter-spacing: -.03em;
  margin-top: .3rem;
}
.plan .price .unit { font-size: .95rem; letter-spacing: 0; margin-left: .15em; }
.plan .perday { font-size: .82rem; color: var(--faint); margin-top: .35rem; }
.plan.best .perday { color: var(--butter-ink); }
.plan .btn { margin-top: 1.1rem; width: 100%; }
.plan .tag {
  position: absolute;
  top: -.7rem;
  left: 50%;
  transform: translateX(-50%);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: #fff;
  background: var(--ember);
  border: 1px solid var(--ember-edge);
  padding: .2rem .65rem;
  border-radius: 999px;
  white-space: nowrap;
}

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

.table-scroll { overflow-x: auto; margin-top: 2.5rem; }
.compare {
  width: 100%;
  border-collapse: collapse;
  font-size: .95rem;
  min-width: 26rem;
}
.compare th, .compare td {
  padding: .8rem .6rem;
  border-bottom: 1px solid var(--border-strong);
  text-align: left;
}
.compare th:not(:first-child), .compare td:not(:first-child) { text-align: center; width: 7rem; }
.compare thead th {
  font-weight: 700;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
}
.compare .yes { color: var(--ok); font-weight: 700; }
.compare .no { color: var(--faint); }
.band.dark .compare .yes { color: #6fd39a; }

/* --- callout ------------------------------------------------------------ */

.callout {
  margin-top: 2rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-left: 4px solid var(--ember);
  border-radius: var(--radius-sm);
  padding: 1.1rem 1.25rem;
  font-size: .95rem;
  color: var(--muted);
}

/* --- faq ---------------------------------------------------------------- */

.faq { margin-top: 2rem; }
.faq details { border-bottom: 1px solid var(--border-strong); padding: 1.05rem 0; }
.faq summary { cursor: pointer; font-weight: 700; list-style: none; padding-right: 2rem; position: relative; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: -.1rem;
  font-family: var(--font-display);
  color: var(--ember);
}
.faq details[open] summary::after { content: "\2013"; }
.faq details p { margin-top: .75rem; color: var(--muted); max-width: var(--measure); }

/* --- prose pages -------------------------------------------------------- */

.prose { max-width: 44rem; padding-block: 2.5rem 4.5rem; }
.prose h1 { font-size: clamp(2.1rem, 6vw, 3.1rem); }
.prose h2 {
  font-size: 1.15rem;
  margin-top: 2.5rem;
  font-family: var(--font);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  line-height: 1.3;
}
.prose p, .prose li { color: var(--muted); margin-top: .95rem; }
.prose li { margin-top: .45rem; }
.prose strong { color: var(--ink); }
.prose ol, .prose ul { padding-left: 1.2rem; }
.prose .updated {
  font-size: .85rem;
  color: var(--faint);
  margin-top: .75rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 600;
}
.prose code {
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: .12em .38em;
  font-size: .88em;
}

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

footer { background: var(--charcoal); color: #cfc5b6; padding-block: 2.5rem 3rem; font-size: .92rem; }
footer .links { display: flex; gap: 1.25rem; flex-wrap: wrap; margin-bottom: 1rem; font-weight: 600; }
footer a { color: #f5efe4; text-decoration: none; }
footer a:hover { text-decoration: underline; }
footer .mark { color: #f5efe4; margin-bottom: 1.1rem; }


/* --- motion on scroll ----------------------------------------------------- */

/* The hidden state is scoped to `html.motion`, which motion.js adds only when
   it has actually run AND the visitor has not asked for reduced motion. With
   no JavaScript, or with reduced motion, none of these rules ever match and
   the page renders plainly — content is never left invisible waiting for a
   script that failed to load. */

/* The reveal is a keyframe ANIMATION, not a transition, and that distinction
   is load-bearing.

   As a transition it read `transition: opacity, transform` plus a staggered
   `transition-delay` on `.reveal.in` — a selector that outranks `.card` and
   `.card:hover`. Three things followed: box-shadow dropped out of the
   transition list so the hover shadow snapped in instantly; the stagger delay
   was inherited by the hover transition; and `transform: none` beat the hover
   lift outright, so the card could not move at all. Buttons were unaffected
   only because they are not reveal targets.

   An animation keeps `transform` and `transition` free for the hover state.
   `backwards` fill holds the start frame through the stagger delay, and once
   the animation finishes it stops applying anything, so hover owns the
   element again. */
html.motion .reveal { opacity: 0; }

html.motion .reveal.in {
  opacity: 1;
  animation: reveal-rise var(--bounce-slow) var(--bounce) backwards;
  /* Children of one group stagger, so a row of cards arrives as a sequence
     rather than as a single block. --i is set per card by motion.js. */
  animation-delay: calc(var(--i, 0) * 65ms);
}

@keyframes reveal-rise {
  from { opacity: 0; transform: translateY(26px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* The hero's marker sweeps in left to right, like it was drawn. */
html.motion .hl {
  background-image: linear-gradient(var(--butter), var(--butter));
  background-repeat: no-repeat;
  background-size: 0% 100%;
  background-color: transparent;
}
html.motion .hl.in {
  background-size: 100% 100%;
  transition: background-size 520ms var(--bounce-soft) 180ms;
}

@media (prefers-reduced-motion: reduce) {
  html.motion .reveal,
  html.motion .reveal.in { opacity: 1; transform: none; animation: none; }
  html.motion .hl,
  html.motion .hl.in { background-size: 100% 100%; transition: none; }
  .btn, .card, .plan, .tile { transition: none; }
  .card:hover, .plan:hover { transform: none; }
}

/* Printing happens without scrolling, so anything still waiting to be revealed
   would come out blank. Force the revealed state on paper. */
@media print {
  html.motion .reveal,
  html.motion .reveal.in { opacity: 1 !important; transform: none !important; animation: none !important; }
  html.motion .hl { background-size: 100% 100% !important; }
}

/* The no-JavaScript pricing list. Never seen alongside the real cards: a
   <noscript> body is inert whenever scripting is on. */
.plans-fallback { list-style: none; padding: 0; margin: 2rem 0 0; }
.plans-fallback li { padding: .6rem 0; border-bottom: 1px solid var(--border); }
