/* ============================================================================
   alfreshco — shared site styles.
   One stylesheet for every page. Asset URLs resolve relative to this file,
   so they work identically from /, /about/ and /work/<slug>/.
   ========================================================================== */

@import "tokens/colors.css";
@import "tokens/effects.css";

:root {
  --pf-page-max: 1440px;
  --pf-side-margin: 120px;

  /* Exact stacks used across the site — no Georgia fallback on the serif,
     matching what shipped. */
  --pf-serif: 'Piazzolla', serif;
  --pf-sans: 'Inter', sans-serif;
  --pf-mono: 'Roboto Mono', ui-monospace, Menlo, monospace;

  /* Display sizes are read off the 1440px Figma canvas (96px / 24px) and
     scale with the viewport below it, so the hero never outgrows a laptop. */
  --pf-display: clamp(44px, 7.4vw, 96px);
  --pf-lede: clamp(19px, 1.9vw, 24px);
}

/* --- Page shell ----------------------------------------------------------- */

/* Horizontal overflow is clipped on <html> only, and only here.
   Repeating overflow-x on <body> (or giving either one height:100%) turns
   <body> into a scroll container: window scroll events stop firing, so
   site.js goes deaf, and position:sticky resolves against a box that never
   scrolls. That is what used to break the sticky header and the case-study
   rail — keep both off <body>. */
html { overflow-x: hidden }

body {
  margin: 0;
  background: var(--surface-page);
  font-family: var(--pf-sans);
}

::selection { background: var(--accent-primary); color: #fff }
::-moz-selection { background: var(--accent-primary); color: #fff }

.pf-page-shell {
  max-width: var(--pf-page-max);
  min-height: 100vh;
  margin: 0 auto;
  background: var(--surface-page);
}

.pf-section { background: var(--surface-page) }

/* --- Custom cursor (desktop, fine-pointer only) ----------------------------
   Progressive enhancement: site.js only creates the .pf-cursor element and
   adds the html.pf-cursor-on class once it confirms a fine pointer with
   hover support, so if JS never runs the native cursor is untouched — no
   pure-CSS `cursor: none` here. Position tracks the mouse 1:1, no follow
   lag: a cursor replacement that trails the real pointer reads as broken
   input, not as delight, so only the hover colour-change animates. That
   change reuses the site's expo-out/expo-in curve pair with a faster exit
   than enter, same as every other hover state on the page. */

html.pf-cursor-on * { cursor: none }

.pf-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: 0;
  transition: opacity .15s cubic-bezier(.16,1,.3,1);
}

.pf-cursor.is-active { opacity: 1 }

.pf-cursor-dot {
  position: absolute;
  top: -5px;
  left: -5px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--text-ghost);
  transition: background-color .1s cubic-bezier(.7,0,.84,0);
}

.pf-cursor.is-hovering .pf-cursor-dot {
  background: var(--accent-primary);
  transition: background-color .15s cubic-bezier(.16,1,.3,1);
}

/* --- Links ---------------------------------------------------------------- */

/* Colour is the instant "you're hovering" feedback; the underline is the
   bolder flourish that follows a beat behind it on the way in. Leaving is
   quicker than arriving (exit ~60% of enter) so the state doesn't linger. */
.pf-a {
  position: relative;
  display: inline-block;
  align-self: flex-start;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: color .12s ease-in;
}

.pf-a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -5px;
  height: 7px;
  background-color: var(--accent-primary);
  mask-image: url(assets/doodles/underline-zigzag.svg);
  -webkit-mask-image: url(assets/doodles/underline-zigzag.svg);
  mask-repeat: repeat-x;
  -webkit-mask-repeat: repeat-x;
  mask-size: 16px 7px;
  -webkit-mask-size: 16px 7px;
  clip-path: inset(0 100% 0 0);
  transition: clip-path .26s cubic-bezier(.7,0,.84,0);
  pointer-events: none;
}

.pf-a:hover { color: var(--accent-primary); transition-timing-function: ease-out; transition-duration: .16s }
.pf-a:hover::after {
  clip-path: inset(0 0 0 0);
  transition: clip-path .42s cubic-bezier(.16,1,.3,1) .04s;
}

/* --- Logo ----------------------------------------------------------------- */

/* colour/decoration reset so the alt text degrades sanely if the SVG 404s */
.pf-logo { position: relative; display: block; width: 155px; height: 50px; cursor: pointer;
  color: inherit; text-decoration: none }
.pf-logo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; transition: opacity .15s ease }
.pf-logo .pf-logo-hover { opacity: 0 }
.pf-logo:hover .pf-logo-default { opacity: 0 }
.pf-logo:hover .pf-logo-hover { opacity: 1 }

/* --- Buttons -------------------------------------------------------------- */

.pf-btn {
  position: relative;
  overflow: visible;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--pf-serif);
  font-weight: 600;
  font-size: 15px;
  padding: 10px 18px;
  text-decoration: none;
  border: var(--border-hard);
  box-shadow: var(--shadow-offset-rest);
  transition: var(--shadow-transition);
  cursor: pointer;
}

.pf-btn:hover { transform: var(--shadow-hover-transform); box-shadow: var(--shadow-offset-hover); transition: var(--shadow-transition-hover) }
.pf-btn:active { transform: var(--shadow-press-transform); box-shadow: var(--shadow-offset-active); transition: var(--shadow-transition-active) }

.pf-btn--accent { background: var(--accent-primary); color: var(--text-on-accent); --pf-doodle-color: var(--text-primary) }
.pf-btn--ghost  { background: var(--surface-page); color: var(--text-primary) }

.pf-btn-row { display: flex; gap: 16px }

/* Doodles that pop out on hover. Colour follows the button variant; the
   default (orange) applies to ghost buttons. The overshoot spring is
   reserved for arriving (the expressive, portfolio-flourish moment);
   leaving is a quicker, un-bouncy fade so it doesn't linger. */
.pf-btn-doodle {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transform: scale(.7) rotate(-6deg);
  transition: opacity .14s cubic-bezier(.7,0,.84,0), transform .2s cubic-bezier(.7,0,.84,0);
  background-color: var(--pf-doodle-color, var(--accent-primary));
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
}

.pf-btn:hover .pf-btn-doodle {
  opacity: 1;
  transform: scale(1) rotate(0deg);
  transition: opacity .2s cubic-bezier(.16,1,.3,1), transform .35s cubic-bezier(.34,1.56,.64,1);
}
.pf-btn:active .pf-btn-doodle { opacity: 0 !important; transition: opacity .08s cubic-bezier(.7,0,.84,0) }

.pf-btn-doodle-scribble { top: -14px; left: -16px; width: 32px; height: 29px;
  mask-image: url(assets/doodles/doodle-scribble.svg); -webkit-mask-image: url(assets/doodles/doodle-scribble.svg) }
.pf-btn-doodle-zigzag { bottom: -17px; right: -16px; width: 32px; height: 36px;
  mask-image: url(assets/doodles/doodle-zigzag.svg); -webkit-mask-image: url(assets/doodles/doodle-zigzag.svg) }
.pf-btn-doodle-alt-1 { bottom: -14px; left: -16px; width: 32px; height: 29px;
  mask-image: url(assets/doodles/doodle-alt-1.svg); -webkit-mask-image: url(assets/doodles/doodle-alt-1.svg) }
.pf-btn-doodle-alt-2 { top: -17px; right: -16px; width: 32px; height: 36px;
  mask-image: url(assets/doodles/doodle-alt-2.svg); -webkit-mask-image: url(assets/doodles/doodle-alt-2.svg) }

.pf-btn:hover .pf-btn-doodle-scribble,
.pf-btn:hover .pf-btn-doodle-alt-1 { animation: pf-btn-wiggle-a 1.6s ease-in-out .1s infinite }
.pf-btn:hover .pf-btn-doodle-zigzag,
.pf-btn:hover .pf-btn-doodle-alt-2 { animation: pf-btn-wiggle-b 1.9s ease-in-out .1s infinite }

@keyframes pf-btn-wiggle-a { 0%,100% { transform: scale(1) rotate(-3deg) } 50% { transform: scale(1) rotate(4deg) } }
@keyframes pf-btn-wiggle-b { 0%,100% { transform: scale(1) rotate(2deg) translateY(0) } 50% { transform: scale(1) rotate(-2deg) translateY(-2px) } }

/* --- Section divider ------------------------------------------------------ */

/* Starts at the gutter and bleeds to the actual viewport edge on wide
   screens — same calc as .pf-carousel-bleed, since .pf-page-shell caps out
   at --pf-page-max and centers, so a plain 100%-wide div stops at the
   shell's edge, not the browser's. */
/* Hidden for now — revisit once the surrounding section spacing is settled. */
.pf-divider { display: none; height: 1px; background: var(--border-color-divider); margin-left: var(--pf-side-margin); width: calc(100% - var(--pf-side-margin) + max(0px, (100vw - var(--pf-page-max)) / 2)) }

/* --- Tags ----------------------------------------------------------------- */

.pf-tag {
  font: 600 10.5px/1 var(--pf-mono);
  letter-spacing: .03em;
  padding: 5px 8px;
  border: 1px solid var(--border-color-hairline);
  color: var(--text-tag);
  text-transform: uppercase;
}

/* --- Kickers & headings --------------------------------------------------- */

/* Section label shared by the home carousel head and the experience head. */
.pf-section-title { font: 600 22px/1.27 var(--pf-serif); color: var(--text-primary) }
.pf-section-title--muted { color: var(--text-secondary) }

.pf-lede { font-weight: 300; font-size: 17px; line-height: 1.55; color: var(--text-secondary); margin: 0 }

/* Big intro copy: Inter ExtraLight at the display scale. The one emphasised
   word ("Abraham") steps up a weight instead of italicising, which is why
   <em> is reset here rather than left at the browser default. */
.pf-lede--big { font-weight: 200; font-size: var(--pf-lede); line-height: 1.2 }
.pf-lede--big em { font-style: normal; font-weight: 400 }

/* --- Site navigation (standalone pages) ----------------------------------- */

.pf-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px var(--pf-side-margin);
  background: var(--surface-page);
}

.pf-nav-links { display: flex; gap: 28px; font-size: 16px; font-weight: 300; color: var(--text-primary) }

/* --- Compact sticky header (home) ----------------------------------------- */

/* Same expo-out/expo-in curve pair as the link hover underline, so the
   header's slide reads as part of the same motion language. Hiding is
   quicker than showing (exit ~65% of enter) since the user has already
   seen it and just wants it out of the way. */
.pf-compact-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px var(--pf-side-margin);
  background: var(--surface-page);
  color: var(--text-primary);
  box-sizing: border-box;
  position: fixed;
  top: 0;
  left: 50%;
  width: min(100%, var(--pf-page-max));
  z-index: 50;
  transform: translateX(-50%) translateY(-110%);
  opacity: 0;
  pointer-events: none;
  transition: transform .18s cubic-bezier(.7,0,.84,0), opacity .14s cubic-bezier(.7,0,.84,0);
}

.pf-compact-header.is-visible {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
  pointer-events: auto;
  transition: transform .28s cubic-bezier(.16,1,.3,1), opacity .2s cubic-bezier(.16,1,.3,1);
}

/* --- Home ----------------------------------------------------------------- */

.pf-home-stage { position: relative; padding: 200px var(--pf-side-margin) 120px; background: var(--surface-page) }
.pf-home-column { width: 800px; max-width: 100% }
.pf-home-intro { margin-top: 120px }

.pf-hero-title { font-family: var(--pf-serif); font-weight: 700; font-size: var(--pf-display); line-height: 1.08; margin: 0 0 22px; color: var(--text-primary) }
.pf-hero-lede { font-weight: 200; font-size: var(--pf-lede); line-height: 1.2; color: var(--text-secondary); margin: 0 }

/* The two nav links live inside the sentence, so they carry the accent at
   rest rather than only on hover — they are the page's only navigation. */
.pf-hero-lede .pf-a { color: var(--accent-primary); font-weight: 400 }

/* Sits inline after the headline so it reflows with it instead of overlapping
   at narrow widths. Same mask-and-tint trick as the button doodles above. */
.pf-hero-doodle {
  display: inline-block;
  width: 30px;
  height: 29.6px;
  vertical-align: .55em;
  margin-left: 14px;
  transform: rotate(-15.84deg);
  background-color: var(--accent-primary);
  mask-image: url(assets/doodles/doodle-smiley.svg);
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
  -webkit-mask-image: url(assets/doodles/doodle-smiley.svg);
  -webkit-mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
}

.pf-home-work { padding: 64px 0 0; background: var(--surface-page); position: relative; scroll-margin-top: 130px }

/* 20px here + the carousel's 20px top padding is the 40px gap in the design;
   the carousel keeps its own padding as overflow room for shadows and doodles. */
.pf-work-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 40px; padding: 0 var(--pf-side-margin) }

.pf-carousel-controls { display: flex; gap: 8px; flex: none }
.pf-carousel-btn { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  padding: 0; background: none; border: 0; color: inherit; cursor: pointer }
.pf-arrow {
  display: block;
  transition: transform .12s cubic-bezier(.7,0,.84,0);
}
.pf-arrow path { fill: var(--text-primary); transition: fill .12s cubic-bezier(.7,0,.84,0) }
/* Hover is scoped to the glyph, not the 44px hit area — as it shipped.
   Same expo-out/expo-in curve pair as the rest of the site: colour and a
   small scale lift arrive together on hover, press flattens for tactile
   click feedback, both release quickly via the base rule above. */
.pf-arrow:hover {
  transform: scale(1.08);
  transition: transform .15s cubic-bezier(.16,1,.3,1);
}
.pf-arrow:hover path {
  fill: var(--accent-primary);
  transition: fill .15s cubic-bezier(.16,1,.3,1);
}
.pf-arrow:active {
  transform: scale(.92);
  transition: transform .1s cubic-bezier(.16,1,.3,1);
}

/* Bleeds the carousel into the right gutter on wide viewports. */
.pf-carousel-bleed { position: relative; width: calc(100% + max(0px, (100vw - var(--pf-page-max)) / 2)) }

.pf-carousel {
  display: flex;
  gap: 24px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--pf-side-margin);
  scroll-behavior: smooth;
  padding: 20px 4px 64px var(--pf-side-margin);
}

.pf-carousel::-webkit-scrollbar { display: none }
.pf-carousel-item { flex: 0 0 auto; scroll-snap-align: start }

/* --- Project card --------------------------------------------------------- */

.pf-card { display: flex; flex-direction: column; gap: 14px; font-family: var(--pf-sans) }
.pf-card-foot { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px }
.pf-card-title { font-family: var(--pf-serif); font-weight: 500; font-size: 19px; color: var(--text-primary) }
.pf-card-sub { font-size: 14px; color: var(--text-card-sub); margin-top: 4px }
.pf-card .pf-btn { flex: none }

/* The full-bleed logo card thumbnail, also the link to the case study. */
.pf-shots {
  display: block;
  width: fit-content;
  line-height: 0;
  color: inherit;
  text-decoration: none;
}

.pf-shots img { height: 400px; width: auto; display: block }

/* --- Standalone page body ------------------------------------------------- */

.pf-page-body { padding: 120px var(--pf-side-margin) 40px; max-width: 760px }
.pf-page-body--full { max-width: none }

/* Stacked intro copy: one gap value instead of per-paragraph margins. */
.pf-page-intro { display: flex; flex-direction: column; gap: 12px }
.pf-page-intro > * { margin: 0 }
.pf-page-intro-copy { display: flex; flex-direction: column; gap: 20px; padding: 40px 0 }
.pf-page-intro .pf-btn-row { padding-top: 8px }

/* --- Experience timeline (about) ------------------------------------------
   Three static columns: when / where / what. There is no hover reveal any
   more, so nothing here animates and the rows are not interactive. */

.pf-xp-wrap { padding: 40px var(--pf-side-margin) 120px }
.pf-xp-head { display: flex; align-items: flex-start; justify-content: space-between; border-bottom: 1px solid var(--border-color-head); padding-bottom: 14px }
.pf-xp { display: grid; grid-template-columns: 140px 1fr minmax(240px, max-content); gap: 32px; padding: 26px 0; border-bottom: 1px solid var(--border-color-default) }
.pf-xp:last-child { border-bottom: 0 }
.pf-xp-range { font-size: 14px; font-weight: 600; color: var(--text-primary) }
.pf-xp-dur { font-size: 13px; color: var(--text-meta-subtle) }
.pf-xp-role { font-family: var(--pf-serif); font-weight: 600; font-size: 20px; line-height: 1.25; margin: 0; color: var(--text-primary) }
.pf-xp-note { font-family: var(--pf-sans); font-style: italic; font-weight: 300; font-size: 17px; line-height: 1.55; color: var(--text-secondary) }
.pf-xp-tags { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; align-content: flex-start }

/* --- Case study ----------------------------------------------------------- */

/* The body is fluid, not capped: at the 1440px canvas it resolves to the
   design's 936px column (1440 - 2x120 gutter - 200 rail - 64 gap). */
.pf-cs-layout { display: flex; gap: 64px; padding: 120px var(--pf-side-margin) 0; align-items: flex-start }
.pf-cs-rail { width: 200px; flex: none; position: sticky; top: 40px; padding-top: 6px }

/* One rhythm for the whole article: 40px between sections, 24px inside one.
   Individual elements carry no margins, so nothing has to be tuned per pair. */
.pf-cs-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 40px; padding-bottom: 60px }
.pf-cs-section { display: flex; flex-direction: column; gap: 24px }
.pf-cs-section > * { margin: 0 }

.pf-cs-navitem {
  display: block;
  text-decoration: none;
  font-size: 14px;
  line-height: 1.3;
  padding: 9px 0 9px 16px;
  cursor: pointer;
  border-left: 2px solid transparent;
  color: var(--text-meta-subtle);
  /* 400, not 500: the Google Fonts request on every page carries Inter
     200/300/400/600/700, so a 500 here is silently synthesised. */
  font-weight: 400;
  transition: color .15s ease, border-color .15s ease;
}

.pf-cs-navitem.is-active { border-left-color: var(--accent-primary); color: var(--text-primary); font-weight: 700 }

.pf-cs-kicker { font: 600 11px/1 var(--pf-mono); color: var(--accent-primary); margin-bottom: 14px }
.pf-cs-h1 { font-family: var(--pf-serif); font-weight: 500; font-size: 34px; line-height: 1.15; margin: 0 0 16px; color: var(--text-primary) }

.pf-cs-meta { display: flex; gap: 40px; font-size: 13px; color: var(--text-meta); flex-wrap: wrap; border-bottom: 1px solid var(--border-color-soft); padding-bottom: 26px }
.pf-cs-meta b { display: block; color: var(--text-primary); margin-bottom: 3px }
.pf-cs-meta-wide { max-width: 620px }

.pf-cs-h2 { font-family: var(--pf-serif); font-weight: 600; font-size: 20px; line-height: 1; color: var(--text-primary); scroll-margin-top: 32px }

.pf-cs-p { font-size: 15px; line-height: 1.65; color: var(--text-secondary) }
.pf-cs-list { font-size: 15px; line-height: 1.8; color: var(--text-secondary); padding-left: 20px }

/* A link sitting on its own line (not inline inside a paragraph) reads as a
   standalone CTA, so it takes the accent colour at rest instead of relying
   on hover to reveal it. */
.pf-cs-section > .pf-a { color: var(--accent-primary) }

/* height:auto is required, not redundant: these <img> tags carry width/height
   attributes (to avoid layout shift before load), and with no CSS height
   declared, browsers fall back to the raw attribute pixel value instead of
   scaling with width — squishing the image. */
.pf-cs-img { width: 100%; height: auto; display: block; border: 1px solid var(--border-color-card) }

/* Live Figma embed, sized off the iframe's own 800x450 so it stays
   responsive instead of carrying fixed pixel dimensions. */
.pf-cs-embed { width: 100%; aspect-ratio: 800 / 450; border: 1px solid var(--border-color-card); overflow: hidden }
.pf-cs-embed iframe { width: 100%; height: 100%; display: block; border: 0 }

.pf-cs-caption { font-size: 12px; color: var(--text-meta-subtle) }

.pf-cs-note { border: 1px solid var(--border-color-card); padding: 20px 22px }
.pf-cs-note-title { font-family: var(--pf-serif); font-style: italic; font-weight: 600; font-size: 15px; color: var(--text-primary); margin-bottom: 8px }
.pf-cs-note-body { font-size: 13.5px; line-height: 1.6; color: var(--text-meta-subtle) }

/* --- Before/after compare slider -------------------------------------------
   Two full-bleed images stacked; the top one is clipped with clip-path so it
   never needs a resize recalculation, just a percentage. Tabs swap which
   panel is visible; every slider stays bound from page load, so switching
   tabs never needs to re-run the drag setup. */
.pf-compare-tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--border-color-soft) }
.pf-compare-tab {
  font: 600 11px/1 var(--pf-mono);
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--text-meta-subtle);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 0 0 12px;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.pf-compare-tab:hover { color: var(--text-primary) }
.pf-compare-tab.is-active { color: var(--accent-primary); border-bottom-color: var(--accent-primary) }
.pf-compare-panel[hidden] { display: none }

.pf-compare { position: relative; width: 100%; aspect-ratio: 2400 / 1589; overflow: hidden; border: 1px solid var(--border-color-card); background: var(--surface-card); cursor: ew-resize; touch-action: pan-y; user-select: none }
.pf-compare > img, .pf-compare-overlay img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none }
.pf-compare-overlay { position: absolute; inset: 0; clip-path: inset(0 50% 0 0) }
.pf-compare:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 3px }
.pf-compare-handle { position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; background: var(--accent-primary); transform: translateX(-50%) }
.pf-compare-grip { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 44px; height: 44px; display: block; pointer-events: none }

/* --- Password gate ---------------------------------------------------------
   The otodom case study ships encrypted (see public/unlock.js); this is what
   stands in for it until it's unlocked. Same 120px gutter as .pf-cs-layout so
   the page doesn't shift when the real content replaces it.

   These are the first input styles in the file. They follow the house rules
   rather than inventing a form language: hard corners, the same 2px border as
   .pf-btn, and the accent outline used by .pf-compare:focus-visible. */

.pf-lock-wrap { padding: 120px var(--pf-side-margin); max-width: 640px }

/* Matches .pf-cs-h1 / .pf-cs-kicker exactly, so unlocking doesn't restyle the
   page under the visitor. Longhand rather than a font: shorthand token — this
   stylesheet imports only tokens/colors.css and tokens/effects.css, so the
   type scale in tokens/typography.css is not available here. */
.pf-lock-title { font-family: var(--pf-serif); font-weight: 500; font-size: 34px; line-height: 1.15; margin: 0 0 16px; color: var(--text-primary) }
.pf-lock-lede { font-weight: 300; font-size: 17px; line-height: 1.55; color: var(--text-secondary); margin: 0 0 36px }

.pf-lock { display: flex; flex-direction: column; gap: 10px }
.pf-lock-label { font: 600 11px/1 var(--pf-mono); letter-spacing: .05em; text-transform: uppercase; color: var(--text-meta-subtle) }
.pf-lock-row { display: flex; gap: 12px; align-items: stretch; flex-wrap: wrap }

.pf-lock-input {
  flex: 1 1 220px;
  min-width: 0;
  font: 400 15px/1 var(--pf-sans);
  color: var(--text-primary);
  background: var(--surface-page);
  border: var(--border-hard);
  border-radius: 0;
  padding: 12px 14px;
}

.pf-lock-input:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 3px }
.pf-lock-input[aria-invalid="true"] { border-color: var(--accent-primary) }

/* Holds its line box even when empty, so an error never nudges the layout.
   The error colour is driven by a class from unlock.js: the message is a
   sibling of .pf-lock-row, not of the input, so no combinator reaches it. */
.pf-lock-msg { font-size: 13px; line-height: 1.5; color: var(--text-meta-subtle); margin: 6px 0 0; min-height: 1.5em }
.pf-lock-msg.is-error { color: var(--accent-primary) }

/* .pf-a is color:inherit with a hover-reveal underline — right for nav, wrong
   for the mailto in the noscript fallback, which is the only way out for a
   visitor without JavaScript, and invisible on touch where there is no hover.
   Tint at rest, the same way .pf-footer-links does. */
.pf-lock-msg .pf-a { color: var(--accent-primary) }
.pf-lock[aria-busy="true"] .pf-btn { opacity: .6 }
.pf-lock .pf-btn[disabled] { cursor: default }

/* Carousel badge marking a card as gated, so the lock isn't a surprise on
   arrival. Reuses the .pf-tag look rather than adding a second chip style. */
.pf-card-lock { display: inline-block; margin-top: 10px }

/* --- Footer --------------------------------------------------------------- */

.pf-footer { background: var(--surface-page); color: var(--text-primary); padding: var(--pf-side-margin) }
.pf-footer-sign { font-family: var(--pf-serif); font-style: italic; font-weight: 600; font-size: 20px; margin-bottom: 14px }
.pf-footer-links { display: flex; gap: 12px; font-size: 14px; color: var(--accent-primary) }
.pf-footer-legal { font-size: 12px; color: var(--text-meta-subtle); margin-top: 14px }

/* --- Narrow viewports ----------------------------------------------------- */

/* The 120px gutter is a 1440px-canvas value; step it down before it starts
   eating the content column on laptops. */
@media (max-width: 1100px) {
  :root { --pf-side-margin: 60px }
}

@media (max-width: 760px) {
  :root { --pf-side-margin: 24px }

  .pf-xp { grid-template-columns: 1fr; gap: 12px }
  .pf-xp-tags { justify-content: flex-start }

  .pf-compact-header { padding: 18px 24px; gap: 18px; align-items: flex-start; flex-direction: column }
  .pf-compact-header .pf-logo { width: 130px; height: 42px }
  .pf-compact-nav { flex-wrap: wrap; gap: 18px !important; font-size: 15px !important; line-height: 1.4 }

  /* The 882px card would otherwise push its title and CTA off-screen inside
     the carousel. Pin the card to the viewport so the copy and button stay
     reachable. */
  .pf-carousel-item { width: calc(100vw - 48px) }
  .pf-card { width: 100% }
  .pf-shots { width: 100%; box-sizing: border-box }
  .pf-shots img { width: 100%; height: auto }
  .pf-card-foot { flex-direction: column; align-items: flex-start; gap: 14px }

  .pf-home-stage { padding: 120px 24px 72px }
  .pf-home-intro { margin-top: 44px }
  .pf-home-work { padding-top: 48px; scroll-margin-top: 160px }
  .pf-hero-doodle { width: 24px; height: 23.7px; margin-left: 10px }

  .pf-page-body { padding: 72px 24px 32px }
  .pf-xp-wrap { padding: 32px 24px 72px }

  /* The rail turns into a horizontal scroller above the article. */
  .pf-cs-layout { flex-direction: column; align-items: stretch; gap: 24px; padding-top: 72px }
  .pf-lock-wrap { padding: 72px var(--pf-side-margin) }
  .pf-cs-rail { position: static; width: 100%; display: flex; overflow-x: auto; padding-top: 0 }
  .pf-cs-navitem { border-left: 0; border-bottom: 2px solid transparent; padding: 8px 14px 8px 0; white-space: nowrap }
  .pf-cs-navitem.is-active { border-left-color: transparent; border-bottom-color: var(--accent-primary) }

  .pf-footer { padding: 72px 24px }
}

/* --- Reduced motion --------------------------------------------------------
   Kept last in the cascade deliberately: several of these selectors tie in
   specificity with the "real" hover/state rules declared earlier in this
   file (e.g. .pf-arrow:hover, .pf-btn:hover .pf-btn-doodle), so this block
   only wins the tie — and actually disables those transitions — because it
   is the last thing the parser sees. Moving it earlier silently breaks it. */
@media (prefers-reduced-motion: reduce) {
  .pf-a,
  .pf-a::after,
  .pf-compact-header,
  .pf-compact-header.is-visible,
  .pf-btn,
  .pf-btn:hover,
  .pf-btn:active,
  .pf-btn-doodle,
  .pf-btn:hover .pf-btn-doodle,
  .pf-btn:active .pf-btn-doodle,
  .pf-arrow,
  .pf-arrow path,
  .pf-arrow:hover,
  .pf-arrow:hover path,
  .pf-arrow:active,
  .pf-cursor,
  .pf-cursor-dot,
  .pf-cursor.is-hovering .pf-cursor-dot { transition: none }

  .pf-btn:hover .pf-btn-doodle-scribble,
  .pf-btn:hover .pf-btn-doodle-alt-1,
  .pf-btn:hover .pf-btn-doodle-zigzag,
  .pf-btn:hover .pf-btn-doodle-alt-2 { animation: none }

  /* site.js swaps its own scrollTo/scrollIntoView calls to `auto`; this is the
     CSS half of the same promise, for the carousel's own scroll container. */
  .pf-carousel { scroll-behavior: auto }
}
