:root{
  /* base = the swatch pack's own white paper (sampled #F7F6F5) */
  --paper:#F7F6F5; --paper-2:#ECEAE6; --card:#FCFBF8;
  --ink:#241A20; --ink-soft:#4A3D44;
  /* legacy accent names now resolve INTO the paper system - coral is THE accent */
  /* MAIN ACCENT = the pack's olive paper (+ text-safe olive-deep); couch green = stamps/handwriting only */
  --olive-deep:#6F672E;
  --red:var(--coral); --red-deep:var(--olive-deep); --blue:var(--powder); --purple:var(--lilac); --yellow:var(--butter); --pink:var(--blush);
  /* "couch green" - sampled from Sofia's velvet couch (IMG_2559), 8.2:1 on paper */
  --green:#274B48; --green-deep:#22403E;
  --speckle:url("assets/textures/speckle_kraft.webp");
  /* THE 8 PAPERS - north star, sampled from the torn-swatch pack (assets/props/sq_*.png) */
  --coral:#FC8078; --tangerine:#FF9C58; --butter:#F8D77A; --olive-p:#D4C47F;
  --blush:#F5BCB2; --lilac:#DFC3D8; --powder:#CCD9DD; --mint:#CCE3BB;
  /* card tints now point at the papers */
  --pink-t:var(--blush); --blue-t:var(--powder); --yellow-t:var(--butter); --red-t:var(--blush);
  /* motion. The stock CSS easings are too soft to read as intentional; these are the
     strong variants. --ease-paper is the hand-tuned curve the ransom letters use - it is
     Sofia-approved, so it stays exactly as-is. */
  --ease-out: cubic-bezier(.23,1,.32,1);
  --ease-paper: cubic-bezier(.2,.75,.3,1);
  --sh-paper: 0 4px 14px rgba(36,26,32,.16), 0 1px 3px rgba(36,26,32,.10);
  --sh-lift: 0 10px 24px rgba(36,26,32,.20), 0 2px 5px rgba(36,26,32,.12);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0; background:var(--paper); color:var(--ink);
  /* nothing visible renders in this stack - every text element names its own family.
     Inter was dropped from the font request because it drew zero pixels. */
  font-family:system-ui,-apple-system,sans-serif; line-height:1.55;
  overflow-x:hidden; position:relative;
}
/* fine paper grain - sits over every section's paper, scrolls with the page */
body::before{
  content:""; position:absolute; inset:0; z-index:3; pointer-events:none; opacity:.4;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.35'/></svg>");
}
/* the scanner-bed vignette stays fixed to the viewport (it's the lens, not the paper) */
html::before{
  content:""; position:fixed; inset:0; z-index:1; pointer-events:none; mix-blend-mode:multiply;
  background:radial-gradient(ellipse 120% 100% at 50% 42%, transparent 62%, rgba(36,26,32,.09) 100%);
}
.wrap{max-width:1160px;margin:0 auto;padding:0 28px;position:relative;z-index:2}
a{color:inherit}
.mono{font-family:"JetBrains Mono",monospace;text-transform:uppercase;letter-spacing:.14em;font-size:.7rem}
/* Courier Prime is NO LONGER LOADED - its catalog/receipt copy was cut, so it was
   drawing zero pixels. This falls back to system Courier; re-add the webfont to the
   <link> in both pages if deadpan spec copy ever returns. */
.type{font-family:"Courier Prime","Courier New",monospace}
.hand{font-family:"Caveat",cursive}
.serif{font-family:"Playfair Display",serif}
.script{font-family:"Pinyon Script",cursive;font-weight:400}
:focus-visible{outline:3px solid var(--green);outline-offset:3px;border-radius:4px}

/* page-corner metadata (zine spread corners) */
.pagehead{display:flex;justify-content:space-between;gap:16px;padding:0 2px;margin-bottom:26px;color:var(--ink-soft)}
.pagehead .mono{font-size:.62rem}

/* NAV */
nav{position:relative;z-index:5;display:flex;align-items:center;justify-content:space-between;padding:22px 28px;max-width:1160px;margin:0 auto}
.brand{font-family:"Playfair Display",serif;font-weight:900;font-size:1.62rem;letter-spacing:-.01em}
.brand span{color:var(--olive-deep)}
.navlinks{display:flex;gap:30px;align-items:center}
/* nav in Playfair italic - masthead voice, matches the "Faria" lockup */
.navlinks a:not(.btn){text-decoration:none;font-family:"Playfair Display",serif;font-style:italic;
  font-weight:500;font-size:1.14rem;letter-spacing:0;color:var(--ink);
  padding:2px 1px 4px;border-bottom:2px solid transparent;transition:border-color .2s,color .2s}
.navlinks a:not(.btn):hover{border-color:var(--green);color:var(--green)}

/* buttons = paper stickers, not web pills */
/* buttons = real torn paper strips */
.btn{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:"JetBrains Mono",monospace;text-transform:uppercase;letter-spacing:.1em;font-size:.7rem;font-weight:700;
  background:url("assets/props/strip_olive.webp") center/100% 100% no-repeat;
  color:var(--ink);border:none;padding:14px 24px;text-decoration:none;
  filter:drop-shadow(2px 3px 4px rgba(36,26,32,.25));
  transition:transform .18s var(--ease-out), filter .18s var(--ease-out)}
.btn:hover{transform:translateY(-2px) rotate(-.6deg);filter:drop-shadow(3px 6px 8px rgba(36,26,32,.3))}
.btn:active{transform:scale(.97) translateY(1px);filter:drop-shadow(1px 1px 2px rgba(36,26,32,.25))}
.btn.ghost{background-image:url("assets/props/strip_white.webp");color:var(--ink)}
/* the one exit from #work, out to the full archive - centred under the 3-card grid */
.worklink{display:flex;justify-content:center;margin-top:56px}
.worklink .btn{padding:16px 32px;font-size:.74rem}

/* HERO BAND - the torn grid page laid on the pack's mint paper (mint peeks = frame) */
.heroband{position:relative;background:var(--mint);padding:16px 0 36px;overflow:hidden}
.heroband::before{content:"";position:absolute;inset:14px;z-index:1;
  background:url("assets/textures/gridpage.webp") center top/cover no-repeat;
  filter:drop-shadow(0 6px 16px rgba(36,26,32,.22))}
/* keep hero content off the sheet's edges so the binder holes + margins stay visible */
.heroband>.wrap{position:relative;z-index:2;padding-left:clamp(44px,8.5vw,132px);padding-right:clamp(28px,4vw,64px)}

/* HERO */
/* hero rhythm tiers: 12 inside a unit, 30 between units, 52 before the CTAs */
.hero{display:grid;grid-template-columns:1.05fr .95fr;gap:40px;align-items:center;padding:48px 0 66px;position:relative}
.hello{font-family:"Caveat",cursive;font-size:clamp(2.9rem,4vw,3.9rem);line-height:1;color:var(--green-deep);transform:rotate(-3deg);display:inline-block;margin-bottom:12px}
h1.title{margin:6px 0 6px;line-height:.98;letter-spacing:-.01em}
/* name lockup sits straight on the hero's grid page - no second sheet behind it */
.namepage{position:relative;display:inline-block}
/* ransom-note first name - native PSD layer cutouts (props/letters/) */
.ransom{display:flex;align-items:center;gap:.4vw;height:clamp(3.6rem,7.8vw,6.2rem)}
/* each letter keeps its own resting angle in a custom prop so hover can add to it */
.ransom img{height:100%;width:auto;--r:-3deg;--ty:0px;position:relative;
  transform:rotate(var(--r)) translateY(var(--ty));
  filter:drop-shadow(2px 3px 3px rgba(36,26,32,.2));
  will-change:transform, filter;
  /* the shadow gets a shorter, front-loaded curve - on `ease` its slow start read as a
     delay, because the shadow only deepens where the lift visibly travels */
  transition:transform .22s cubic-bezier(.2,.75,.3,1), filter .12s cubic-bezier(.2,.75,.3,1)}
.ransom img:nth-child(even){--r:2.5deg;--ty:3px}
/* hover = one cutout peeling up off the page, not a bounce.
   z-index is required: siblings paint in DOM order, so without it the next
   letter slices the lifted letter's shadow in half. */
.ransom img:hover{z-index:2;transform:rotate(var(--r)) translateY(calc(var(--ty) - 7px));
  filter:drop-shadow(3px 8px 8px rgba(36,26,32,.3))}
.lastname{display:block;font-family:"Playfair Display",serif;font-style:italic;font-weight:900;color:var(--green);font-size:clamp(3.4rem,7.8vw,6.2rem);margin-top:6px}
/* lede in Source Serif 4 - editorial warmth, pairs with the Playfair name */
/* the role line is the one fact under the name - it outranks the category list */
.lede{font-family:"Source Serif 4",Georgia,serif;font-size:1.3rem;line-height:1.45;max-width:36ch;
  color:var(--ink);margin:30px 0 30px;font-weight:400;text-wrap:pretty}
/* categories: one typographic line instead of five bordered pills */
.tags{display:flex;flex-wrap:wrap;align-items:center;gap:0 16px;margin-bottom:62px;position:relative}
.tag{font-family:"Playfair Display",serif;font-style:italic;font-weight:500;text-transform:none;
  letter-spacing:0;font-size:1.06rem;color:var(--ink-soft);display:inline-flex;align-items:center;gap:8px;padding:3px 0}
.tag+.tag::before{content:"";width:1px;height:16px;background:rgba(36,26,32,.26);margin-right:16px}
.tag.fill{color:var(--green-deep);font-weight:600}
.tag svg{display:block}
/* cats read like every other category; only the note singles them out */
.tag.cats{position:relative}
/* left:calc(50% - 14px) lands the arrow's tip (top-left of the mirrored svg) on the cats' centre */
.catsnote{position:absolute;top:calc(100% + 6px);left:calc(50% - 14px);white-space:nowrap;pointer-events:none;
  display:flex;align-items:flex-end;gap:4px;font-family:"Caveat",cursive;font-size:1.55rem;line-height:1;
  color:var(--green-deep);transform:rotate(-2deg);
  text-transform:none;letter-spacing:0;font-weight:600}
.catsnote svg{margin-bottom:2px;flex:none}
.tagnote{position:relative;margin:0 0 22px;padding-left:8px}
.tagnote .hand{font-size:1.35rem;color:var(--green-deep);transform:rotate(-2deg);display:inline-block}
.cta-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
/* the only social account. A paper strip like the CTAs, but on CORAL so it reads as a
   different kind of thing than the two olive/white call-to-actions - and it echoes the
   coral heart up in the categories. Ink on coral measures 6.83:1. */
.tiktok{background-image:url("assets/props/strip_coral.webp");gap:9px}
.ttglyph{flex:none}

/* hero art - photo stack pulled toward the middle, leaving the bottom-right for the blooms */
.art{position:relative;min-height:540px;display:flex;justify-content:center;align-items:flex-end;
  padding-right:clamp(0px,11vw,158px)}
/* pressed flowers (real botanical scans, native alpha) */
.bloom{position:absolute;pointer-events:none;z-index:4;filter:drop-shadow(2px 4px 5px rgba(36,26,32,.22))}
/* the two blooms never touch each other or the print - separated vertically */
.bloom1{width:clamp(104px,11vw,150px);right:-34px;bottom:-22px;transform:rotate(-13deg)}
.bloom2{width:clamp(60px,6.4vw,86px);right:60px;bottom:158px;transform:rotate(16deg)}
/* taped photo stack - hover/click cycles through Sofia's portraits */
.photostack{position:relative;z-index:2;width:min(330px,78vw);cursor:pointer}
.photostack .under{position:absolute;inset:0;background:var(--card);transform:rotate(-4.5deg);box-shadow:var(--sh-paper)}
.photostack .under2{position:absolute;inset:0;background:var(--paper-2);transform:rotate(3deg);box-shadow:var(--sh-paper)}
.photostack .print{position:relative;display:block;width:100%;border:10px solid var(--card);border-bottom-width:16px;box-shadow:var(--sh-lift);transform:rotate(1.6deg)}
.photostack .count{position:absolute;bottom:-12px;left:-8px;background:var(--card);border:1.5px solid var(--ink);border-radius:14px 18px 13px 17px/17px 13px 18px 14px;padding:3px 10px;font-size:.56rem;z-index:3;box-shadow:var(--sh-paper)}
/* washi tape - real die-cut strips. RULE: no two placements share the same piece */
.tape{position:absolute;z-index:4;width:148px;aspect-ratio:3.74;transform:rotate(-9deg);
  background:url("assets/props/tape_y1.webp?v3") center/100% 100% no-repeat;
  filter:drop-shadow(1px 2px 2px rgba(36,26,32,.18));opacity:.97}
/* hero: the stack is taped to the page across its top edge */
.photostack .tape{width:152px;top:-18px;left:50%;transform:translateX(-50%) rotate(-3.5deg);z-index:5}
/* prop utilities - kept for rebuilding the collage layer piece by piece */
.prop{position:absolute;mix-blend-mode:multiply;pointer-events:none;z-index:4}
/* die-cut stickers - real alpha, sit on top with a sticker lift */
.stickr{position:absolute;pointer-events:none;z-index:4;filter:drop-shadow(1px 3px 4px rgba(36,26,32,.28))}
/* SECTIONS - each one its own full-bleed sheet of paper */
section.block{position:relative;z-index:2;padding:72px 0 52px;
  margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);
  padding-left:calc(50vw - 50%);padding-right:calc(50vw - 50%)}
/* every section background is one of THE 8 PAPERS, at full strength */
#work{background:url("assets/textures/crumple_tile.webp") top center/100% auto repeat-y}
/* #why = a torn square-holed notebook page laid on the blush paper, so the pink reads as a
   frame around it (same device as the hero band, but a visibly different sheet: square
   punch holes vs the hero's round ones). */
#why{background:var(--blush);position:relative}
/* `100% auto` + `bottom` anchoring is load-bearing: `cover` scaled the 1.92:1 sheet to fill a
   taller box and CROPPED THE TORN BOTTOM EDGE OFF, leaving a plain rectangle. Width now fits
   exactly and any overflow crops from the TOP, which is the sheet's clean straight edge.
   Two stacked shadows = contact + ambient, so the tear reads as paper lying on paper. */
#why::before{content:"";position:absolute;inset:16px;z-index:0;
  background:url("assets/textures/gridpage_sq.webp") center bottom/100% auto no-repeat;
  filter:drop-shadow(0 2px 2px rgba(36,26,32,.22)) drop-shadow(0 10px 20px rgba(36,26,32,.18))}
/* positioned ::before paints above STATIC block children, so the flow content must be lifted
   explicitly. Listed individually - a blanket `#why>*` would beat .bloom on specificity and
   destroy the absolutely-positioned flowers. */
#why>.lettertitle,#why>.why-lede,#why>.reellabel,#why>.reel{position:relative;z-index:1}
/* tighten the run-up so the film sits higher, and open the space beneath it so the sheet's
   torn bottom edge has room to read instead of being crowded by the strip */
#why{padding-bottom:104px}
#why>.lettertitle{margin-bottom:32px}
#why>.why-lede{margin-bottom:28px}
.eyebrow{color:var(--red-deep);margin-bottom:10px}
.h2{font-family:"Playfair Display",serif;font-weight:900;font-size:clamp(2rem,4.5vw,3.1rem);line-height:1;margin:0 0 10px}
.h2 .script{font-size:1.25em;color:var(--red-deep);margin-right:2px}
/* section headings pasted on real torn paper squares */
.titlecard{position:relative;display:inline-block;padding:44px 62px 50px;margin-bottom:14px;filter:drop-shadow(4px 6px 9px rgba(36,26,32,.22))}
.titlecard::before{content:"";position:absolute;inset:0;z-index:-1;background:center/100% 100% no-repeat}
.titlecard.powder::before{background-image:url("assets/props/sq_powder.webp?v2");transform:rotate(-1.6deg)}
.titlecard.blush::before{background-image:url("assets/props/sq_blush.webp?v2");transform:rotate(1.4deg)}
.titlecard.mint::before{background-image:url("assets/props/sq_mint.webp?v2");transform:rotate(-1.2deg)}
.titlecard.lilac::before{background-image:url("assets/props/sq_lilac.webp?v2");transform:rotate(1.8deg)}
.titlecard.coral::before{background-image:url("assets/props/sq_coral.webp?v2");transform:rotate(-1.5deg)}
.titlecard .h2{margin:0}
/* section intros share the hero's editorial body voice; Courier stays for catalog/spec copy */
.sub{font-family:"Source Serif 4",Georgia,serif;color:var(--ink-soft);max-width:56ch;line-height:1.55;margin:0 0 44px;font-size:1.12rem;text-wrap:pretty}
/* WORK - player cards (blue composition) */
/* letters pasted straight on the section's paper - no tape behind them, since the
   cutouts already carry their own coloured chips (object on object read as clutter) */
.lettertitle{display:flex;justify-content:center;margin:0 0 54px}
.lettertitle .h2{margin:0;line-height:1;display:flex;font-size:0}
/* section-scale ransom letters - same cutouts + same hover lift as the hero name */
.ransom.sm{height:clamp(2.2rem,3.8vw,3.2rem);gap:.4vw}
.ransom .rsp{flex:none;width:.7em}   /* word space between cutout words */

/* WHY ME - the commercials shown as a strip of film */
.why-lede{max-width:50ch;margin:0 auto 46px;text-align:center}
.reel{position:relative;background:#1B1418;border-radius:3px;padding:32px 0;
  box-shadow:var(--sh-lift);transform:rotate(-.5deg)}
/* sprocket holes, punched top and bottom like real 35mm */
.reel::before,.reel::after{content:"";position:absolute;left:0;right:0;height:32px;z-index:2;
  background-image:radial-gradient(circle, var(--paper) 0 4.5px, transparent 5px);
  background-size:32px 32px;background-position:14px 50%}
.reel::before{top:0}
.reel::after{bottom:0}
.reelstrip{display:flex;gap:10px;padding:0 14px;overflow-x:auto;scrollbar-width:none}
.reelstrip::-webkit-scrollbar{display:none}
.reelframe{flex:none;width:clamp(232px,29vw,330px);aspect-ratio:16/9;position:relative;
  padding:0;font:inherit;color:inherit;cursor:pointer;
  background:#0D090B;border:1px solid rgba(247,246,245,.16);display:grid;place-items:center;
  text-decoration:none;overflow:hidden;transition:transform .2s cubic-bezier(.2,.75,.3,1)}
.reelframe img{width:100%;height:100%;object-fit:cover;display:block}
.reelframe:hover{transform:scale(1.015)}
.reelframe:active{transform:scale(.985)}
.rfnum{position:absolute;top:9px;left:11px;color:rgba(247,246,245,.85);font-size:.58rem;z-index:3;
  text-shadow:0 1px 3px rgba(0,0,0,.7)}
.rfph{color:rgba(247,246,245,.42);font-size:.58rem;letter-spacing:.14em}
/* two more pressed flowers - different species from the hero pair, chosen for contrast:
   cream on the blush paper, mauve resting on the dark film */
/* all three clustered in the open paper right of the lede - a loose triangle, no two touching.
   They must stay ABOVE the reel: the film spans the full content width, so anything level with
   it covers a frame title. */
.bloom3{width:clamp(100px,11vw,150px);top:24px;right:19%;left:auto;transform:rotate(-15deg)}
/* petal heart (rose petals, Valentine ephemera sheet) - heavier in colour than the flowers,
   so it runs smaller to carry the same visual weight */
.bloom5{width:clamp(70px,7vw,95px);top:30px;right:2%;bottom:auto;left:auto;transform:rotate(-9deg);z-index:5}
.bloom4{width:clamp(84px,8.8vw,120px);top:152px;right:6.5%;transform:rotate(13deg);z-index:5}
/* label above the strip so it's obvious what the film is */
.reellabel{margin:0 0 14px;text-align:center;color:var(--ink);font-size:.72rem;opacity:.85}
/* per-frame title, lower-third style. NOT uppercased - brand names need their real casing
   ("iPhone", "AT&T"). The scrim is functional (legibility over any still), not decoration. */
.rftitle{position:absolute;left:0;right:0;bottom:0;z-index:3;padding:26px 12px 10px;
  font-family:"JetBrains Mono",monospace;font-size:.62rem;letter-spacing:.04em;line-height:1.3;
  color:rgba(247,246,245,.95);text-align:left;
  background:linear-gradient(to top, rgba(11,8,9,.92), rgba(11,8,9,.55) 45%, transparent)}
.rftitle b{font-weight:700}
.rftitle i{font-style:normal;opacity:.6}
.rftitle-ph{color:rgba(247,246,245,.4)}
/* filled frames: a play mark, and the still lifts out of the film on hover */
.reelframe img{transition:transform .25s var(--ease-out), filter .25s ease;filter:saturate(.92)}
.reelframe:hover img{transform:scale(1.05);filter:saturate(1.05)}
.rfplay{position:absolute;z-index:3;width:52px;height:52px;border-radius:50%;
  background:rgba(20,14,17,.55);border:1.5px solid rgba(247,246,245,.85);
  backdrop-filter:blur(2px);transition:background .2s ease, transform .2s var(--ease-out)}
.rfplay::after{content:"";position:absolute;top:50%;left:52%;transform:translate(-50%,-50%);
  border-left:15px solid rgba(247,246,245,.95);border-top:9px solid transparent;border-bottom:9px solid transparent}
.reelframe:hover .rfplay{background:rgba(20,14,17,.72);transform:scale(1.06)}
.frames{display:grid;grid-template-columns:repeat(3,1fr);gap:34px;align-items:start}
.frame-wrap:nth-child(2){margin-top:38px}
.frame-wrap:nth-child(3){margin-top:-12px}
.player{position:relative;border:2px solid var(--ink);border-radius:24px 20px 25px 19px/20px 25px 19px 24px;padding:14px 14px 16px;box-shadow:var(--sh-paper);transition:transform .25s var(--ease-out), box-shadow .25s var(--ease-out)}
.player.t1{background:var(--blue-t);transform:rotate(-2.2deg)}
.player.t2{background:var(--yellow-t);transform:rotate(1.4deg)}
.player.t3{background:var(--pink-t);transform:rotate(2.4deg)}
.player:hover{transform:rotate(0) translateY(-4px);box-shadow:var(--sh-lift)}
.screen:active{transform:scale(.985)}
.screen{transition:transform .14s var(--ease-out)}
.player::after{content:"";position:absolute;inset:0;z-index:4;pointer-events:none;border-radius:inherit;
  background:url("assets/textures/speckle_kraft.webp") center/cover;mix-blend-mode:multiply;opacity:.35}
/* the speckle stays on the card's paper but must NOT lie over the footage - it multiplied
   across the video and read as a vintage filter. Screen sits above it; tape and clip number
   move up so the screen doesn't cover them in turn. */
.player .screen{z-index:5}
/* one distinct piece of tape per card - same roll, different tear */
.player .ptape{position:absolute;top:-16px;left:50%;z-index:6;background:center/100% 100% no-repeat;
  filter:drop-shadow(1px 2px 2px rgba(36,26,32,.16));opacity:.97}
.player.t1 .ptape{width:120px;aspect-ratio:2.86;transform:translateX(-50%) rotate(-4deg);background-image:url("assets/props/tape_y2.webp?v3")}
.player.t2 .ptape{width:136px;aspect-ratio:3.55;transform:translateX(-54%) rotate(2.5deg);background-image:url("assets/props/tape_y5.webp?v3")}
.player.t3 .ptape{width:128px;aspect-ratio:4.14;transform:translateX(-46%) rotate(-1.5deg);background-image:url("assets/props/tape_y3.webp?v3")}
/* clip numbers = ransom digit cutouts */
.player .clipno{position:absolute;top:-20px;right:-14px;width:50px;transform:rotate(6deg);z-index:7;filter:drop-shadow(1px 3px 3px rgba(36,26,32,.28))}
/* ransom glyphs inline in headings */
.h2 .glyph{height:.95em;width:auto;vertical-align:-6%;margin-left:8px;transform:rotate(4deg);filter:drop-shadow(1px 2px 2px rgba(36,26,32,.22));display:inline-block}
/* .screen is a <button> where there's a clip (keyboard-reachable, opens the real player)
   and a plain div on the placeholder card - so it carries its own button reset */
.screen{display:block;width:100%;padding:0;font:inherit;color:inherit;cursor:pointer;
  position:relative;border:2px solid var(--ink);border-radius:14px;overflow:hidden;aspect-ratio:9/13;background:var(--ink)}
div.screen{cursor:default}
.screen img,.screen video{width:100%;height:100%;object-fit:cover;display:block}
.ptitle{padding:13px 6px 0;text-align:center}
/* track title in the voice face, meta in mono - two faces per card, not three */
.ptitle .t{font-family:"Playfair Display",serif;font-style:italic;font-weight:600;font-size:1.18rem;
  letter-spacing:0;text-transform:none;display:block;line-height:1.15}
.ptitle .a{font-family:"JetBrains Mono",monospace;text-transform:uppercase;letter-spacing:.1em;
  font-size:.6rem;color:var(--ink-soft);display:block;margin-top:5px}
.pbar{display:flex;align-items:center;gap:8px;padding:10px 8px 2px}
.pbar .time{font-family:"JetBrains Mono",monospace;font-size:.55rem;color:var(--ink-soft)}
.pbar .line{flex:1;height:3px;background:rgba(36,26,32,.25);border-radius:2px;position:relative}
.pbar .line::before{content:"";position:absolute;left:0;top:0;bottom:0;width:34%;background:var(--ink);border-radius:2px}
.pbar .line::after{content:"";position:absolute;left:34%;top:50%;transform:translate(-50%,-50%);width:9px;height:9px;border-radius:50%;background:var(--ink)}
.pctrl{display:flex;align-items:center;justify-content:center;gap:18px;padding:6px 0 0}
.pctrl svg{display:block}
.pctrl .play{width:44px;height:44px;border-radius:50%;background:var(--ink);display:grid;place-items:center;box-shadow:0 3px 6px rgba(36,26,32,.25)}

/* FOOTER - poster on a purple desk */
footer{position:relative;z-index:2;background:var(--butter);padding:86px 0 78px}
footer::before{content:"";position:absolute;inset:0;opacity:.3;mix-blend-mode:multiply;pointer-events:none;
  background:
    radial-gradient(ellipse 130% 110% at 50% 30%, transparent 50%, rgba(36,26,32,.28) 100%),
    var(--speckle) center/cover}
.poster{position:relative;max-width:620px;margin:0 auto;background:var(--card);border-radius:3px;box-shadow:0 14px 30px rgba(36,26,32,.22);padding:54px 46px 44px;text-align:center;transform:rotate(-.8deg)}
/* real crumpled-paper texture over the whole poster, creases fall over the ink like ref 2554 */
.poster::after{content:"";position:absolute;inset:0;z-index:6;pointer-events:none;border-radius:inherit;
  background:url("assets/textures/crumple_cream.webp") center/cover;mix-blend-mode:multiply;opacity:.6}
.poster .corner{position:absolute;font-size:.55rem;color:var(--ink-soft)}
.poster .c-tl{top:14px;left:16px}.poster .c-tr{top:14px;right:16px}.poster .c-bl{bottom:12px;left:16px}.poster .c-br{bottom:12px;right:16px}
/* real photographed paperclip (native aspect ~1:3.9, so width alone sets the clip's length).
   scaleY(-1) puts the closed loop over the paper - the source scan is the other way up.
   Kept hard left: the script headline starts ~53px in, so this is the only column where the
   clip can reach far enough down the page to look like it's actually gripping. */
.paperclip{position:absolute;top:-40px;left:4px;width:34px;transform:rotate(-5deg) scaleY(-1);z-index:7;
  filter:drop-shadow(1px 3px 4px rgba(36,26,32,.34))}
.poster h2{margin:6px 0 4px;line-height:1}
.poster .script{font-size:clamp(3rem,7vw,4.4rem);color:var(--ink);display:block}
/* couch green, not olive: measured on the poster's REAL surface (card + crumple multiply
   at .6 = rgb 241,233,216) olive-deep is 4.76:1 and reads muddy, couch green is 7.96:1.
   Coral 2.05 and tangerine 1.71 both fail large-text AA here, so warm accents can't carry it. */
.poster .serif-line{font-family:"Playfair Display",serif;font-style:italic;font-weight:900;font-size:clamp(1.6rem,3.4vw,2.2rem);color:var(--green);display:block;margin-top:2px}
.poster .sub{margin:16px auto 26px;max-width:40ch;font-size:.88rem}
.foot-row{display:flex;justify-content:center;align-items:center;gap:18px;flex-wrap:wrap;margin-top:34px}
/* the email is the point of this whole section - size it like it. clamp() keeps it inside
   the poster's 231px inner width at 375px while letting it grow to ~1rem on desktop. */
#contact .foot-row .btn{font-size:clamp(.7rem,1.55vw,1rem);
  padding:clamp(15px,1.9vw,23px) clamp(22px,3vw,40px);letter-spacing:.07em}
.foot-links{display:flex;gap:20px;justify-content:center;margin-top:26px}
.foot-links a{display:inline-flex;align-items:center;gap:7px;font-family:"JetBrains Mono",monospace;text-transform:uppercase;letter-spacing:.12em;font-size:.66rem;text-decoration:none;color:var(--ink);border-bottom:2px solid transparent;transition:border-color .2s}
.foot-links a:hover{border-color:var(--red-deep)}
/* the two links that still have no destination - flagged rather than left as dead "#" */
.foot-pending{display:flex;justify-content:center;margin:16px 0 0}
.ph{outline:1.5px dashed rgba(36,26,32,.45);outline-offset:3px;font-size:.55rem;padding:1px 5px}

/* draft banner */
.draftbar{position:relative;z-index:6;background:var(--ink);color:var(--yellow);text-align:center;padding:7px}
.draftbar .mono{font-size:.62rem}
/* set by lightbox.js when the page is opened over file:// - Safari can't play video there */
.draftbar.warn{background:var(--coral);color:var(--ink)}

@media(max-width:900px){
  .hero{grid-template-columns:1fr;gap:34px;padding-top:26px}
  .art{order:-1;min-height:420px}
  .frames{grid-template-columns:1fr;justify-items:center;gap:40px}
  .frame-wrap:nth-child(2),.frame-wrap:nth-child(3){margin-top:0}
  /* ORPHANED PADDING - this inset the lockup for the torn grid strip that used to sit
     behind it (.namepage::before, removed in the 14th pass). Without that sheet it just
     pushed SOFIA/Faria 30px right of "hi, i'm", the lede and the buttons, which is what
     made the hero look accidentally ragged on a phone. Everything aligns at 0 now. */
  .namepage{padding:0}
  /* symmetric gutters. The left was 44px to clear the sheet's punch holes and the right
     was 28px, so the whole column sat off-centre on top of the ragged alignment. */
  .heroband>.wrap{padding-left:34px;padding-right:34px}
  /* the name was pinned at the clamp FLOOR on mobile (7.8vw = 30px at 375, far under the
     3.4rem min), so it never scaled down from desktop - it just sat small. Raise the
     floor for phones. */
  .ransom{height:4.6rem;gap:3px}
  .lastname{font-size:4.3rem}
  .hello{font-size:3rem}
  /* mobile: the cats land mid-line, so hang the note from their RIGHT edge
     (extends leftward, never off-screen) and flip the arrow to point up-right */
  /* narrow column: shrink the note so it clears the punch holes on the left
     while the arrow still lands on the cats rather than past the heart */
  /* The note was anchored to .tag.cats, whose x position moves as the categories rewrap -
     on a narrower iPhone it ran off the screen. Make .tag.cats static so the containing
     block becomes .tags itself, then pin the note to the tags' RIGHT edge: it can no
     longer overflow at any width. Arrow moves to the LEFT of the sentence and points
     back up-left at the cats. */
  .tag.cats{position:static}
  .catsnote{left:auto;right:0;top:calc(100% + 8px);font-size:1.06rem}
  /* #why has no side margins on mobile, so the blooms flank the SHORT title line
     instead of the paragraph - otherwise they sit on top of the copy */
  /* both hung off the viewport edge (-8 / -6) and got sliced by the screen. #why has no
     side margin on a phone, so a negative offset here clips rather than bleeding over a
     margin the way it does on desktop. Keep them fully inside. */
  /* NB each bloom is rotated, so its bounding box is ~15px wider than `width` and the
     rotation shifts it further out - 8px of inset was not enough to clear the edge. */
  /* they must also finish ABOVE the lede's first line - the safe band on a phone is
     between the section top and y~245, flanking the WHY ME? letters on either side */
  .bloom3{width:74px;top:54px;left:16px}
  .bloom5{width:66px;top:70px;right:16px;bottom:auto;left:auto}
  /* 375px has no room for a third bloom without it landing on copy - two is the mobile crop */
  .bloom4{display:none}
  /* narrow column: the blooms tuck into the print's bottom-right corner instead */
  .art{padding-right:0}
  .bloom1{width:84px;right:-2px;bottom:10px}
  .bloom2{width:50px;right:46px;bottom:118px}
  .catsnote svg{order:-1;transform:scaleX(-1)!important;margin-bottom:3px}
  .titlecard{padding:22px 28px 26px}
  .player{width:100%;max-width:330px}
  .navlinks .navonly{display:none}
  /* the wordmark is her full handle now (Sofia.Faria.222) and at 1.62rem it ran straight
     into the "Work with me" button on a phone - they met at exactly 0px gap */
  .brand{font-size:1.3rem}
  .poster{padding:54px 26px 40px}
  /* narrower poster padding leaves no left column, so the clip grips less and stays above the headline */
  .paperclip{width:26px;top:-58px;left:8px}
}
/* Reduced motion means gentler, NOT none. Movement and scaling go; colour, opacity and
   shadow stay, because those carry meaning (hover feedback, the play cue fading out).
   The old rule was `*{transition:none!important}`, which also killed those. */
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .ransom img,.btn,.player,.reelframe,.reelframe img,.rfplay,.screen,.lb-fs,.lb-close,
  .lb-card,.tiktok{transition-property:opacity,color,border-color,background-color,box-shadow,filter}
  .ransom img:hover{transform:rotate(var(--r)) translateY(var(--ty))}
  .btn:hover,.btn:active,.lb-fs:hover,.lb-fs:active,.tiktok:hover{transform:none}
  .lb-close:hover,.lb-close:active,.screen:active,.reelframe:active{transform:none}
  .player:hover{transform:none}
  .reelframe:hover,.reelframe:hover img,.reelframe:hover .rfplay{transform:none}
  .reveal{opacity:1!important;translate:none!important;rotate:none!important}
}

/* ---- LIGHTBOX PLAYER -------------------------------------------------------
   Hover previews are muted because browsers reject unmuted autoplay without a
   user gesture. A CLICK is a gesture, so the real player - sound, scrubbing,
   fullscreen - lives here. Shared by index.html and work.html. */
.lb{position:fixed;inset:0;z-index:200;display:none;place-items:center;padding:24px;
  background:rgba(20,14,17,.88);opacity:0;transition:opacity .2s var(--ease-out)}
.lb.open{display:grid}
/* .in is set one frame after .open so the transition has a start value to run from.
   Exit is faster than enter (150 vs 220) - slow where the user decides, fast where
   the system responds. */
.lb.in{opacity:1}
/* width:max-content lets the card shrink to the video's real aspect - a fixed width
   pillarboxes portrait clips against the black element background */
/* min-width:0 is required - a grid item's default min-width:auto resolves to the video's
   intrinsic width and overrides max-width, pushing the card past the viewport edge */
.lb-card{position:relative;width:max-content;min-width:0;max-width:min(94vw,460px);
  background:var(--card);padding:10px 10px 4px;
  border-radius:12px 8px 13px 7px/7px 13px 8px 12px;box-shadow:0 18px 50px rgba(0,0,0,.5);
  transform:rotate(-.7deg) scale(.96);transition:transform .22s var(--ease-out)}
/* never scale(0) - it reads as appearing out of nowhere. .96 keeps it a real object. */
.lb.in .lb-card{transform:rotate(-.7deg) scale(1)}
.lb.closing{transition-duration:.15s}
.lb.closing .lb-card{transition-duration:.15s}
.lb-card.wide{max-width:min(94vw,940px)}
.lb video{display:block;width:auto;height:auto;max-width:100%;max-height:calc(88vh - 92px);
  background:#000;border:2px solid var(--ink);border-radius:8px}
.lb-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 4px 8px}
.lb-cap{font-family:"Playfair Display",serif;font-style:italic;font-weight:600;font-size:1rem}
.lb-fs{cursor:pointer;border:none;background:url("assets/props/strip_white.webp") center/100% 100% no-repeat;
  font-family:"JetBrains Mono",monospace;text-transform:uppercase;letter-spacing:.1em;
  font-size:.58rem;font-weight:700;color:var(--ink);padding:9px 14px;
  filter:drop-shadow(1px 2px 3px rgba(36,26,32,.25));transition:transform .16s var(--ease-out)}
.lb-fs:hover{transform:translateY(-2px) rotate(-.6deg)}
.lb-fs:active{transform:scale(.97)}
/* the close chip hangs off the corner like a sticker peeled onto the card */
.lb-close{position:absolute;top:-15px;right:-15px;z-index:2;cursor:pointer;border:none;
  width:38px;height:38px;border-radius:50%;background:var(--coral);color:var(--ink);
  font-family:"JetBrains Mono",monospace;font-size:1rem;font-weight:700;line-height:1;
  box-shadow:0 3px 9px rgba(0,0,0,.4);transition:transform .16s var(--ease-out)}
.lb-close:hover{transform:scale(1.08) rotate(6deg)}
.lb-close:active{transform:scale(.94)}
@media(max-width:900px){
  .lb{padding:14px}
  .lb-card,.lb-card.wide{max-width:calc(100vw - 28px);transform:none}
  .lb video{max-height:calc(86vh - 92px)}
  /* the card fills the width here, so a chip hanging off the corner falls off-screen -
     tuck it inside, over the frame, and size both controls for touch (44px) */
  .lb-close{top:16px;right:16px;width:44px;height:44px;box-shadow:0 2px 10px rgba(0,0,0,.55)}
  .lb-fs{padding:14px 18px}
}


/* ---- TOUCH ------------------------------------------------------------------
   On a touch screen :hover latches on after a tap and stays. Reset the hover
   transforms to each element's RESTING value - not `none`, since the paper
   pieces all sit at a resting angle. */
@media (hover: none), (pointer: coarse){
  .ransom img:hover{transform:rotate(var(--r)) translateY(var(--ty));z-index:auto;
    filter:drop-shadow(2px 3px 3px rgba(36,26,32,.2))}
  .btn:hover,.tiktok:hover{transform:none;filter:drop-shadow(2px 3px 4px rgba(36,26,32,.25))}
  .player.t1:hover{transform:rotate(-2.2deg)}
  .player.t2:hover{transform:rotate(1.4deg)}
  .player.t3:hover{transform:rotate(2.4deg)}
  .player:hover{box-shadow:var(--sh-paper)}
  .reelframe:hover{transform:none}
  .reelframe:hover img{transform:none;filter:saturate(.92)}
  .lb-fs:hover,.lb-close:hover{transform:none}
}

/* Cutout letters drop in one after another when the lockup arrives. On desktop this is
   the entrance and hover still does the lift; on touch, where there is no hover, it is
   the only thing that stops the letters reading as a flat image. Uses `translate` and
   `opacity` so the per-letter resting rotation in `transform` survives. */
.ransom.pre img{opacity:0;translate:0 -16px}
.ransom img{transition:transform .22s var(--ease-paper), filter .12s var(--ease-paper),
  opacity .42s var(--ease-out), translate .42s var(--ease-out)}

/* ---- SCROLL REVEAL ----------------------------------------------------------
   Cards lift into place as their section arrives - seen once per visit, so it is
   in the "occasional" tier where a little delight is allowed. Set by JS only, so
   with JS off everything is simply visible. Stagger stays inside Emil's 30-80ms. */
/* uses the independent `translate` property, NOT transform: the tiles and player cards
   each carry a resting rotate() and a hover transform, and a transform-based reveal
   would wipe both out. `translate` composes with them instead. */
.reveal{opacity:0;translate:0 14px;rotate:2.5deg;
  transition:opacity .5s var(--ease-out), translate .5s var(--ease-out), rotate .5s var(--ease-out)}
/* `rotate` is the independent property, so it ADDS to each card's resting transform
   rotation rather than replacing it - the card arrives a few degrees off and settles
   into its angle, like paper being laid down. */
.reveal.in{opacity:1;translate:0 0;rotate:0deg}

/* ---- FOOTER DOODLES --------------------------------------------------------
   Die-cuts from the Scrapbook Doodle Collection, scattered down BOTH butter margins
   either side of the poster. Kraft + black ink on butter is close in value, but each
   piece carries its own cream die-cut outline, which is what separates it from the
   ground - that outline is the whole reason these read on a coloured sheet where the
   photographic cutouts didn't.
   Anchored with calc() off the page centre so they stay level with the 620px poster
   (its edges sit at 50% -+ 310px) instead of drifting with the viewport. */
#contact .wrap{position:relative}
.doodle{position:absolute;z-index:1;pointer-events:none;
  filter:drop-shadow(2px 3px 3px rgba(36,26,32,.22))}
/* Composition: NOT two even columns of three - that reads mechanical. Each side is a
   loose triangle with one dominant piece, a mid, and a small, and the x positions zigzag
   so no three line up. The plane sits on the LEFT because it flies up-and-right, i.e.
   INTO the poster - it is "send a message". The speech bubble answers it from the right.
   Both clusters stay clear of the paperclip at the poster's top-left. */
/* Left gets two, right gets three - an even 3/3 reads mechanical. A small sparkle was
   tried in the left gap and cut: the margin is only ~270px wide, so at any size big
   enough to register it grazed both the plane and the star once rotation inflated its
   box. d_sparkle.png stays in props/doodles/ for a roomier spot. */
/* left - the plane leads */
.dd-plane  {left:calc(50% - 452px);top:18px;  width:122px;transform:rotate(6deg)}
.dd-star   {left:calc(50% - 448px);top:214px; width:86px; transform:rotate(-13deg)}
/* right - the bubble answers */
.dd-bubble {left:calc(50% + 330px);top:46px;  width:120px;transform:rotate(-8deg)}
.dd-shoot  {left:calc(50% + 356px);top:188px; width:104px;transform:rotate(-14deg)}
.dd-heart  {left:calc(50% + 326px);top:302px; width:68px; transform:rotate(16deg)}

@media(max-width:1180px){
  /* margins tighten - shrink and pull in toward the poster, keeping the triangles */
  .dd-plane  {left:calc(50% - 408px);width:102px}
    .dd-star   {left:calc(50% - 404px);width:72px}
  .dd-bubble {left:calc(50% + 316px);width:100px}
  .dd-shoot  {left:calc(50% + 334px);width:88px}
  .dd-heart  {left:calc(50% + 314px);width:58px}
}
@media(max-width:900px){
  /* The poster fills the width - there are no side margins left, only two thin butter
     bands: ~83px above the paper and ~76px below. Keep the two pieces that carry meaning
     and sit them ENTIRELY inside those bands. Anything overlapping the poster's top or
     bottom edge lands on a corner label (CONTACT - 2026 top-right, @handle bottom-left),
     which is exactly what the first attempt did. */
  .doodle{display:none}
  .dd-plane {display:block;left:auto;right:14px;top:-72px;   width:64px;transform:rotate(10deg)}
  .dd-bubble{display:block;left:14px;top:auto;bottom:-70px;  width:68px;transform:rotate(-8deg)}
}
@media(prefers-reduced-motion:reduce){.doodle{transition:none}}

/* very narrow phones (SE-class, 320px): the full handle wordmark plus the CTA do not fit
   the nav at their normal sizes - they met at a 0px gap. Shrink both. */
@media(max-width:400px){
  nav{padding:18px 16px}
  .brand{font-size:1.12rem}
  nav .btn{padding:11px 14px;font-size:.6rem}
}
