/* Portfolio (spec 2026-10-18 section 3): folder cards + sticky filter bar. Dialog styles live in portfolio-modal.css (the review dialog reuses that frame). */
.pf { --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
      --tab: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='32'%3E%3Cpath d='M18 0H72C80 0 85 3 90 9L101 22C106 28 111 30 118 30H150V32H0V18C0 8 8 0 18 0Z'/%3E%3C/svg%3E"); }

/* ---------- grid ---------- */
.pf-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; counter-reset: pf; }
.pf-card:not([hidden]) { counter-increment: pf; }
.pf-card[hidden] { display: none; }
.pf-num::before { content: counter(pf, decimal-leading-zero); }
@media (max-width: 1100px) { .pf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 640px; margin-inline: auto; } }
@media (max-width: 600px) { .pf-grid { grid-template-columns: minmax(0, 1fr); max-width: 420px; gap: 16px; } }

/* ---------- folder card ---------- */
.pf-card {
  --frame: color-mix(in srgb, var(--navy) 62%, var(--blue)); --pocket: var(--navy); --glow-a: var(--cyan); --glow-b: var(--blue); --back: var(--navy);
  --title: var(--white); --desc: rgb(255 255 255 / .68); --num: var(--cyan); --edge: rgb(255 255 255 / .10); --cast: rgb(4 8 20 / .45); --tint: 17 24 39;
  position: relative; display: block; aspect-ratio: 3 / 4; padding: 10px; border-radius: 30px; background: var(--frame);
  box-shadow: inset 0 0 0 1px var(--edge), inset 0 1px 0 rgb(255 255 255 / .14), 0 1px 2px rgb(var(--tint) / .10), 0 8px 16px -6px rgb(var(--tint) / .18), 0 28px 50px -18px rgb(var(--tint) / .35);
  text-decoration: none; text-align: left; transition: opacity var(--t-4) var(--e-out), transform var(--t-2) var(--e-out), box-shadow var(--t-2) var(--e-out);
}
/* Scroll reveal on a card that also lifts on hover: the two share transform, so
   the entrance is a keyframe (fill backwards, so it lets go of transform when
   done) and the reveal stagger moves from transition-delay to animation-delay.
   Otherwise .reveal.in's delay would hold every hover lift back by --i * 70ms. */
.pf-card.reveal.in { transition-delay: 0s; animation: pf-reveal var(--dur, var(--t-4)) var(--e-out) calc(var(--i, 0) * var(--step, 70ms)) backwards; }   /* after a filter change portfolio.js sets --dur to --t-3 and --step to 40ms */
@keyframes pf-reveal { from { opacity: 0; transform: translateY(1.375rem); } }
/* Wato (2026-10-19): the full-cyan folders read too dark and heavy next to the
   site's white cards. The folder is now the site's card material: white frame
   with the --line hairline and --shadow-sm, a pale cyan pocket, the number in
   --cyan-text, cyan kept for the hover ring and the arrow button. */
.pf-card.cyan {
  --frame: var(--white); --edge: var(--line); --tint: 17 24 39;
  --pocket: color-mix(in srgb, var(--cyan) 14%, var(--white)); --back: var(--soft-2);
  --glow-a: color-mix(in srgb, var(--cyan) 45%, var(--white)); --glow-b: color-mix(in srgb, var(--blue) 30%, var(--white));
  --title: var(--ink); --desc: var(--muted); --num: var(--cyan-text); --cast: rgb(17 24 39 / .14);
  box-shadow: inset 0 0 0 1px var(--edge), var(--shadow-sm);
}
.pf-card.cyan .pf-bg::after { opacity: .10; }
.pf-card.cyan .pf-go { background: var(--cyan); color: var(--white); }
.pf-card.cyan .pf-dtags li, .pf-card.cyan .pf-dvisit { background: var(--white); box-shadow: inset 0 0 0 1px var(--line); }
@media (hover: hover) { .pf-card.cyan:hover { box-shadow: inset 0 0 0 1px var(--cyan), var(--shadow); } }
.pf-panel { position: relative; width: 100%; height: 100%; border-radius: 20px; overflow: hidden; isolation: isolate; }
.pf-bg { position: absolute; inset: 0; background: radial-gradient(120% 70% at 15% 0%, var(--glow-a) 0%, transparent 60%), radial-gradient(90% 60% at 100% 30%, var(--glow-b) 0%, transparent 70%), var(--back); transition: transform var(--t-4) var(--e-soft); }
.pf-bg::after { content: ""; position: absolute; inset: 0; background: var(--grain); opacity: .22; mix-blend-mode: overlay; }
.pf-shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; transition: transform var(--t-4) var(--e-soft); }
.pf-who { --who-w: 60%; position: absolute; left: 50%; top: var(--who-top, 6%); width: var(--who-w); margin-left: calc(var(--who-w) / -2); filter: drop-shadow(0 10px 18px rgb(0 0 0 / .25)); transition: transform var(--t-4) var(--e-spring); }
.pf-who--1 { --who-w: 50%; --who-top: 10%; } .pf-who--3 { --who-w: 65%; --who-top: 4%; }
.pf-logo { position: absolute; left: 50%; top: 28%; width: 64%; max-height: 28%; object-fit: contain; transform: translate(-50%, -50%); border-radius: calc(var(--radius) / 2); filter: grayscale(1) contrast(1.2); opacity: .85; transition: filter var(--t-3) var(--e-out), opacity var(--t-3) var(--e-out); }
.pf-card:hover .pf-logo { filter: none; opacity: 1; }
.pf-pocket { position: absolute; left: 0; right: 0; top: 24%; height: 200%; filter: drop-shadow(0 -6px 14px var(--cast)); transition: transform var(--t-4) var(--e-spring); }
.pf-tab { position: absolute; left: 0; top: 0; width: 150px; height: 32px; background: var(--pocket); -webkit-mask: var(--tab) center / cover no-repeat; mask: var(--tab) center / cover no-repeat; }
.pf-body { position: absolute; left: 0; right: 0; top: 30px; bottom: 0; background: var(--pocket); border-radius: 0 20px 0 0; }
.pf-num { position: absolute; left: 20px; top: -4px; margin: 0; font-family: var(--display); font-size: 34px; line-height: 1.2; color: var(--num); }
.pf-go { position: absolute; right: 18px; top: 18px; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--white); color: var(--ink); border: 0; cursor: pointer; box-shadow: var(--shadow-cyan); z-index: 3; }
.pf-go svg { width: 15px; height: 15px; }
.pf-go:focus-visible { outline: 3px solid var(--navy); outline-offset: 3px; }
.pf-text { position: absolute; left: 20px; right: 20px; bottom: 20px; transition: opacity var(--t-3) var(--e-out), transform var(--t-3) var(--e-out); }
.pf-text h3 { margin: 0 0 4px; font: 700 16px/1.2 var(--head); color: var(--title); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pf-text p { margin: 0; font: 600 13px/1.4 var(--font); color: var(--desc); }
.pf-tag { position: absolute; top: 12px; left: 12px; z-index: 2; padding: 5px 10px; border-radius: 999px; font: 700 10.5px/1.2 var(--head); letter-spacing: .08em; text-transform: uppercase; color: var(--white); background: rgb(8 12 24 / .32); -webkit-backdrop-filter: blur(10px) saturate(160%); backdrop-filter: blur(10px) saturate(160%); border: 1px solid rgb(255 255 255 / .25); transition: opacity var(--t-2) var(--e-out); }
.pf-details { position: absolute; left: 20px; right: 20px; top: 48px; display: grid; gap: 9px; color: var(--ink); opacity: 0; transform: translateY(10px); pointer-events: none; transition: opacity var(--t-3) var(--e-out), transform var(--t-3) var(--e-out); }
.pf-dtitle { margin: 0; font: 800 16px/1.2 var(--head); }
.pf-ddesc { margin: 0; font-size: 13px; line-height: 1.4; color: rgb(8 8 8 / .72); display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.pf-dmore { margin: 0; font: 700 13px/1.2 var(--head); }
.pf-dmeta { display: flex; gap: 18px; margin: 2px 0 0; } .pf-dmeta div { display: grid; gap: 1px; }
.pf-dmeta dt { font: 700 10px/1.2 var(--head); letter-spacing: .1em; text-transform: uppercase; color: rgb(8 8 8 / .5); } .pf-dmeta dd { margin: 0; font: 600 13px/1.3 var(--font); }
.pf-dtags { display: flex; flex-wrap: wrap; gap: 5px; margin: 2px 0 0; padding: 0; list-style: none; }
.pf-dnote { margin: 0; font-size: 13px; line-height: 1.4; color: rgb(8 8 8 / .72); }
.pf-dvisit { justify-self: start; padding: 4px 9px; border-radius: 999px; background: rgb(255 255 255 / .85); font: 600 11.5px/1.2 var(--font); color: var(--ink); text-decoration: none; }
.pf-card.is-shut .pf-dvisit { pointer-events: auto; }
@media (hover: hover) { .pf-card:hover .pf-dvisit, .pf-card:focus-within .pf-dvisit, .pf-card.is-shut .pf-dvisit { pointer-events: auto; } }
.pf-dtags li { padding: 4px 9px; border-radius: 999px; background: rgb(255 255 255 / .85); font: 600 11.5px/1.2 var(--font); color: var(--ink); }
.pf-shot--card, .pf-logo { transition: transform var(--t-4) var(--e-soft), opacity var(--t-3) var(--e-out), filter var(--t-3) var(--e-out); }

/* states: open (rest) vs shut (hover on hover devices, focus-within, .is-shut on touch) */
.pf-card .pf-pocket { transform: translateY(13.5%); }
.pf-card .pf-who { transform: rotate(-4deg); }
.pf-card .pf-bg, .pf-card .pf-shot { transform: scale(1.15); }
@media (hover: hover) {
  .pf-card:hover .pf-pocket, .pf-card:focus-within .pf-pocket, .pf-card.is-shut .pf-pocket { transform: none; }
  .pf-card:hover .pf-who, .pf-card:focus-within .pf-who, .pf-card.is-shut .pf-who { transform: translateY(140px) rotate(0deg); }
  .pf-card:hover .pf-bg, .pf-card:hover .pf-shot, .pf-card:focus-within .pf-bg, .pf-card:focus-within .pf-shot, .pf-card.is-shut .pf-bg, .pf-card.is-shut .pf-shot { transform: none; }
  .pf-card:hover .pf-details, .pf-card:focus-within .pf-details, .pf-card.is-shut .pf-details { opacity: 1; transform: none; transition-delay: 120ms; }
  .pf-card:hover .pf-text, .pf-card:focus-within .pf-text, .pf-card.is-shut .pf-text { opacity: 0; transform: translateY(8px); }
  .pf-card:hover .pf-tag, .pf-card:focus-within .pf-tag, .pf-card.is-shut .pf-tag { opacity: 0; }
  .pf-card:hover { transform: translateY(var(--lift)); box-shadow: inset 0 0 0 1px var(--edge), inset 0 1px 0 rgb(255 255 255 / .14), 0 2px 4px rgb(var(--tint) / .10), 0 14px 24px -8px rgb(var(--tint) / .22), 0 40px 70px -20px rgb(55 189 242 / .45); }
  .pf-card[data-kind="web"], .pf-card[data-kind="project"] { cursor: pointer; }
}
@media (hover: none) {
  .pf-card.is-shut .pf-pocket { transform: none; }
  .pf-card.is-shut .pf-who { transform: translateY(140px) rotate(0deg); }
  .pf-card.is-shut .pf-bg, .pf-card.is-shut .pf-shot { transform: none; }
  .pf-card.is-shut .pf-details { opacity: 1; transform: none; }
  .pf-card.is-shut .pf-text, .pf-card.is-shut .pf-tag { opacity: 0; }
}
.pf-card .pf-shot.pf-shot--card, .pf-card:hover .pf-shot.pf-shot--card, .pf-card:focus-within .pf-shot.pf-shot--card, .pf-card.is-shut .pf-shot.pf-shot--card { left: 0; right: 0; top: 4%; width: 100%; height: 70%; object-fit: contain; object-position: center; transform: none; }
/* the same scene, blurred and darkened, fills the window behind the contained card (a cover crop of the 16:9 scene in a 3:4 window would cut the card itself); the scale hides the blur's soft edge */
.pf-card .pf-shot.pf-shot--card-bg, .pf-card:hover .pf-shot.pf-shot--card-bg, .pf-card:focus-within .pf-shot.pf-shot--card-bg, .pf-card.is-shut .pf-shot.pf-shot--card-bg { object-fit: cover; object-position: center; filter: blur(14px) brightness(.85); transform: scale(1.15); }
/* clients: business card at rest, character rises on shut; pocket never moves */
.pf-card[data-kind="client"] .pf-who { transform: translateY(130%) rotate(0deg); }
.pf-card[data-kind="client"] .pf-pocket { transform: translateY(13.5%); }
@media (hover: hover) {
  .pf-card[data-kind="client"]:hover .pf-shot--card, .pf-card[data-kind="client"]:focus-within .pf-shot--card, .pf-card[data-kind="client"].is-shut .pf-shot--card,
  .pf-card[data-kind="client"]:hover .pf-logo, .pf-card[data-kind="client"]:focus-within .pf-logo, .pf-card[data-kind="client"].is-shut .pf-logo { opacity: 0; }
  .pf-card[data-kind="client"]:hover .pf-who, .pf-card[data-kind="client"]:focus-within .pf-who, .pf-card[data-kind="client"].is-shut .pf-who { transform: rotate(-4deg); }
  .pf-card[data-kind="client"]:hover .pf-pocket, .pf-card[data-kind="client"]:focus-within .pf-pocket, .pf-card[data-kind="client"].is-shut .pf-pocket { transform: translateY(13.5%); }
}
@media (hover: none) {
  .pf-card[data-kind="client"].is-shut .pf-shot--card, .pf-card[data-kind="client"].is-shut .pf-logo { opacity: 0; }
  .pf-card[data-kind="client"].is-shut .pf-who { transform: rotate(-4deg); }
  .pf-card[data-kind="client"].is-shut .pf-pocket { transform: translateY(13.5%); }
}
.pf-card:focus-within { outline: 3px solid var(--cyan); outline-offset: 4px; }
@media (prefers-reduced-motion: reduce) { .pf-card, .pf-pocket, .pf-who, .pf-bg, .pf-shot, .pf-logo, .pf-details, .pf-text { transition-duration: 200ms !important; transition-timing-function: ease !important; } }

/* review card: a navy chat card the size of the folders; the quote is cut off, click opens it (P13, P17) */
@media (max-width: 600px) { .pf-card { aspect-ratio: 1 / 1; } }
.pf-review { padding: 1rem; border-radius: 30px; background: var(--navy); border: 0; box-shadow: var(--shadow); cursor: pointer; min-width: 0; }
.pf-review__inner { position: relative; height: 100%; display: flex; flex-direction: column; gap: .8rem; padding-bottom: 1.2rem; overflow: hidden; }
.pf-review .chat-msg[data-side="staff"] { margin-top: auto; }
.pf-review .chat-msg { max-width: 100%; min-width: 0; } .pf-review .chat-msg > div, .pf-review-dialog .chat-msg > div { min-width: 0; } .pf-review .bubble, .pf-review-dialog .bubble { overflow-wrap: anywhere; }
.pf-review .bubble { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; padding-bottom: 0; border-bottom: .65rem solid var(--white); } /* bottom gap is a border so clipped lines never peek through the padding */
.pf-review .chat-msg[data-side="staff"] .bubble { border-bottom-color: var(--cyan); }
.pf-review .chat-msg[data-side="client"] .bubble { -webkit-line-clamp: 5; }
.pf-review .chat-msg[data-side="staff"] .bubble { -webkit-line-clamp: 2; }
.pf-rmore { position: absolute; right: .25rem; bottom: 0; font: 700 .72rem/1 var(--head); color: var(--cyan-light); letter-spacing: .04em; }
:is(.pf-review, .pf-review-dialog) .msg-who { color: rgba(255,255,255,.72); }
:is(.pf-review, .pf-review-dialog) .msg-who b { color: var(--cyan-light); }
:is(.pf-review, .pf-review-dialog) .av { border-color: rgba(55,189,242,.55); }
@media (hover: hover) { .pf-review:hover { transform: translateY(var(--lift)); box-shadow: var(--shadow), 0 40px 70px -20px rgb(55 189 242 / .45); } }
.pf-review:focus-visible { transform: translateY(var(--lift)); box-shadow: var(--shadow), 0 40px 70px -20px rgb(55 189 242 / .45); }
.pf-review:focus:not(:focus-visible), .pf-review:focus-within:not(:focus-visible) { outline: none; }
.pf-review:focus-visible { outline: 3px solid var(--cyan); outline-offset: 4px; }
.pf-review-dialog { max-width: min(42rem, 94vw); }
.pf-review-dialog .portfolio-modal__inner { padding: 1.5rem; display: grid; gap: .8rem; }
.pf-review-dialog__body { display: grid; gap: 1rem; }
.pf-review-dialog__body { padding-top: 1.6rem; }
.pf-review-dialog .chat-msg { max-width: 100%; }
.pf-review-dialog .chat-msg[data-side="staff"] { align-self: flex-end; }

/* ---------- filter bar ---------- */
.pf-sentinel { height: 1px; }
.pf-filterwrap { position: sticky; top: var(--pf-top, 0px); z-index: 20; padding: 12px 0 var(--space-md); margin-bottom: 0; display: grid; justify-items: center; }
.pf-filterwrap::before { content: ""; position: absolute; z-index: -1; top: 0; bottom: 0; left: 50%; width: 100vw; transform: translateX(-50%); background: var(--soft); opacity: 0; transition: opacity var(--t-2) var(--e-out); }
.pf-filterwrap.is-stuck::before { opacity: 1; }
.pf-filter { width: 100%; display: grid; justify-items: center; gap: 12px; }
.pf-segs { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.pf-filter .pf-seg { padding: .8rem 1.3rem; }
.pf-seg b, .pf-chip b { font-weight: 600; font-size: .8em; opacity: .6; margin-left: 3px; }
.pf-seg .short { display: none; }
.pf-chips { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 8px; animation: pf-chips-in var(--t-3) var(--e-out); }
.pf-chips[hidden] { display: none; }
.pf-sep { width: 1px; height: 1.4rem; background: var(--line); margin-inline: 6px; }
@keyframes pf-chips-in { from { opacity: 0; transform: translateY(-6px); } }
.pf-seg:focus-visible, .pf-chip:focus-visible { outline: 3px solid var(--cyan); outline-offset: 2px; }
.pf-filterwrap.is-stuck { padding-top: 6px; padding-bottom: 8px; } .pf-filterwrap.is-stuck .pf-filter { gap: 8px; }
.pf-filterwrap.is-stuck .pf-filter .pf-seg { padding: .6rem 1.1rem; } .pf-filterwrap.is-stuck .pf-chip { padding: .55rem .9rem; }
.pf-result { position: absolute; right: 0; top: 18px; height: 41px; margin: 0; display: flex; align-items: center; font: 600 13px var(--font); color: var(--muted); transition: top var(--t-2) var(--e-out), height var(--t-2) var(--e-out); }
.pf-filterwrap.is-stuck .pf-result { top: 12px; height: 34px; }
/* ---------- page chrome: breadcrumb + hero (pages.css is not loaded here, so the pillar-hero rhythm is repeated) ---------- */
.pf-crumb { padding: 0; border-bottom: 1px solid var(--line); background: linear-gradient(180deg, #eaf5fe 0%, #f6fbff 60%, #fff 100%); }
.pf-crumb .container { padding-block: .625rem; }
.pf-crumb .breadcrumb { font-size: .82rem; color: var(--muted); display: flex; flex-wrap: wrap; align-items: center; gap: .4375rem; }
.pf-crumb .breadcrumb a { color: var(--cyan-text); text-decoration: none; } .pf-crumb .breadcrumb a:hover { text-decoration: underline; }
.pf-hero { padding-block: 2.375rem .625rem; }
.pf-hero h1 { margin: .5rem 0 .875rem; }
.pf-hero .pillar-lead { font-size: 1.15rem; line-height: 1.6; color: var(--body); max-width: 80ch; margin: 0; }
section.soft.pf { padding-block: var(--space-sm) var(--space-xl); }
/* Wato 2026-10-19: no floating characters on the portfolio, like the support page */
body[data-no-eggs] .wato-egg { display: none !important; }
::view-transition-group(*) { animation-duration: var(--t-3); animation-timing-function: var(--e-out); }
@media (max-width: 600px) {
  .pf-result { position: static; height: auto; justify-content: center; margin-top: 8px; } .pf-filterwrap.is-stuck .pf-result { height: auto; }
  .pf-filterwrap { padding-inline: 12px; }
  .pf-segs { flex-wrap: nowrap; gap: 6px; max-width: 100%; } .pf-filter .pf-seg { padding: .7rem .9rem; font-size: .85rem; }
  .pf-seg .long { display: none; } .pf-seg .short { display: inline; }
  .pf-chips { gap: 6px; } .pf-sep { display: none; } .pf-chip { padding: .6rem .8rem; }
  /* stuck on a phone (Wato 2026-11-06, too much crammed in): one row of pills over one quiet row of chips.
     The chips drop their counts and glow, so the four platforms fit a 390 screen with the next group peeking;
     the row runs edge to edge and fades out on the right to show it scrolls. About 85px tall at 390. */
  .pf-filterwrap.is-stuck .pf-result { display: none; }
  .pf-filterwrap.is-stuck .pf-filter { gap: 6px; }
  .pf-filterwrap.is-stuck .pf-segs { gap: 5px; }
  .pf-filterwrap.is-stuck .pf-filter .pf-seg { padding: .5rem .65rem; font-size: .8rem; }
  .pf-filterwrap.is-stuck .pf-chips { flex-wrap: nowrap; justify-content: flex-start; gap: 5px; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; width: 100vw; margin-inline: calc((100% - 100vw) / 2); padding: 2px 2.75rem 2px 1rem; -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 2.75rem), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 2.75rem), transparent); }
  .pf-filterwrap.is-stuck .pf-chips::-webkit-scrollbar { display: none; }
  .pf-filterwrap.is-stuck .pf-chip { flex: none; padding: .55rem .7rem; font-size: .74rem; box-shadow: none; }
  .pf-filterwrap.is-stuck .pf-chip b { display: none; }
  .pf-filterwrap.is-stuck .pf-sep { display: block; flex: none; height: 1rem; margin-inline: 3px; }
}
@media (max-width: 420px) { .pf-seg b { display: none; } }
