/* ═══════════════════════════════════════════════════════════════════════════
   Portfolio — the public page
   ───────────────────────────────────────────────────────────────────────────
   One stylesheet for every portfolio, whatever template it started from. The
   differences between templates live in the document (its theme variables and
   the styles on each block), not here, so a client who moves everything around
   still gets a page that holds together.

   Everything is driven by the eight variables the page sets on :root. This
   file is deliberately small: it is on the critical path of a stranger's first
   visit, usually on a phone, often on mobile data.
   ═══════════════════════════════════════════════════════════════════════════ */

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

.pf-body {
  margin: 0;
  background: var(--pf-bg, #fff);
  color: var(--pf-text, #101828);
  font-family: var(--pf-font, Inter, system-ui, sans-serif);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }

/* ── the draft notice ───────────────────────────────────────────────────── */
.pf-draft {
  background: #1f2937; color: #fff;
  font-family: Inter, system-ui, sans-serif;
  font-size: 13px; text-align: center;
  padding: 10px 16px;
  position: sticky; top: 0; z-index: 20;
}

/* ── structure ──────────────────────────────────────────────────────────── */
.pf-section { position: relative; }
.pf-wrap {
  max-width: var(--pf-max, 1140px);
  margin: 0 auto;
  padding-left: 24px; padding-right: 24px;
}
.pf-row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 32px;
  align-items: start;
}
.pf-col { min-width: 0; }
/* A row of cards should end level. Only the columns that hold one stretch,
   so an ordinary two-column row still sizes to its content. */
.pf-col:has(> .pf-pk), .pf-col:has(> .pf-service) { align-self: stretch; }
.pf-col > .pf-pk, .pf-col > .pf-service { height: 100%; }
.pf-col-1  { grid-column: span 1; }
.pf-col-2  { grid-column: span 2; }
.pf-col-3  { grid-column: span 3; }
.pf-col-4  { grid-column: span 4; }
.pf-col-5  { grid-column: span 5; }
.pf-col-6  { grid-column: span 6; }
.pf-col-7  { grid-column: span 7; }
.pf-col-8  { grid-column: span 8; }
.pf-col-9  { grid-column: span 9; }
.pf-col-10 { grid-column: span 10; }
.pf-col-11 { grid-column: span 11; }
.pf-col-12 { grid-column: span 12; }

/* ── blocks ─────────────────────────────────────────────────────────────── */
.pf-h {
  margin: 0 0 16px;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 700;
  color: inherit;
}
.pf-h:last-child { margin-bottom: 0; }

.pf-text { color: var(--pf-muted, #5f6a7d); }
.pf-text p { margin: 0 0 14px; }
.pf-text p:last-child { margin-bottom: 0; }

.pf-fig { margin: 0; }
.pf-fig img {
  width: 100%;
  border-radius: var(--pf-radius, 14px);
  object-fit: cover;
}

/* A block with no image yet, on the public page as well as in the builder:
   an empty gap reads as a broken page, a marked one reads as unfinished. */
.pf-ph {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--pf-radius, 14px);
  background: var(--pf-surface, #f6f7f9);
  color: var(--pf-muted, #5f6a7d);
  display: flex; align-items: center; justify-content: center;
  opacity: .55;
}
.pf-ph svg { width: 38px; height: 38px; }

/* Set the way a studio would set it: small, tracked and in capitals rather
   than a large web button. The size difference is what separates a
   photographer's site from an app's landing page. */
.pf-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 15px 30px;
  background: var(--pf-accent, #4f46e5);
  color: #fff;
  border-radius: var(--pf-radius, 14px);
  font-size: 13px; font-weight: 650;
  letter-spacing: .09em; text-transform: uppercase;
  text-decoration: none;
  transition: opacity .15s ease, transform .15s ease;
}
.pf-btn:hover { opacity: .9; transform: translateY(-1px); }

.pf-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}
/* The frame is fixed and the picture moves inside it, very slightly, on
   hover. A gallery that answers the pointer reads as a portfolio; one that
   sits still reads as a contact sheet. */
.pf-gallery figure {
  margin: 0; overflow: hidden;
  border-radius: var(--pf-radius, 14px);
}
.pf-gallery img,
.pf-gallery .pf-ph {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--pf-radius, 14px);
  transition: transform .6s cubic-bezier(.2, .7, .3, 1);
}
.pf-gallery figure:hover img { transform: scale(1.035); }

.pf-video {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  border-radius: var(--pf-radius, 14px); overflow: hidden;
  background: var(--pf-surface, #f6f7f9);
}
.pf-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.pf-social { display: flex; flex-wrap: wrap; gap: 10px; }
.pf-social a {
  display: inline-flex; align-items: center;
  padding: 9px 16px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 13.5px; font-weight: 600;
  text-decoration: none;
  color: var(--pf-muted, #5f6a7d);
  transition: color .15s ease;
}
.pf-social a:hover { color: var(--pf-accent, #4f46e5); }
/* Centred by the block's own alignment rather than by a second rule. */
[style*="text-align:center"] > .pf-social,
.pf-social[style*="text-align:center"] { justify-content: center; }

/* A block narrower than its column that centres its own text is centred as
   a whole. Without this, a 620px lede in a centred section sat hard against
   the left edge with its words centred inside it, which reads as a mistake
   rather than as a measure. */
[style*="text-align:center"][style*="max-width"] { margin-left: auto; margin-right: auto; }

.pf-contact { font-size: 20px; font-weight: 600; }
.pf-contact a { color: var(--pf-accent, #4f46e5); text-decoration: none; }
.pf-contact a:hover { text-decoration: underline; }

.pf-quote {
  margin: 0;
  padding: 30px 32px 28px;
  background: var(--pf-surface, #f6f7f9);
  border-radius: var(--pf-radius, 14px);
}
/* A quotation mark set in the page's own display face, large and faint. It
   is decoration, so it is hidden from anything reading the page aloud. */
.pf-quote::before {
  content: "\201C";
  display: block; margin-bottom: -14px;
  font-size: 56px; line-height: 1;
  color: var(--pf-accent, #4f46e5); opacity: .32;
}
/* The size is set on the quotation, and the paragraphs inside it follow.
   Setting it on the paragraph instead meant a template asking for a 24px
   pull quote got 17px, because this file is more specific than the block. */
.pf-quote { font-size: 17px; }
.pf-quote p { margin: 0 0 14px; font-size: inherit; line-height: 1.7; }
.pf-quote cite {
  font-style: normal; font-size: 13px; font-weight: 650;
  color: var(--pf-muted, #5f6a7d);
}

/* A hairline over each service turns three paragraphs into a set. Neutral,
   so it reads the same on a near-black template as on an off-white one. */
.pf-service { padding-top: 20px; border-top: 1px solid rgba(128,128,128,.28); }
.pf-service h3 {
  margin: 0 0 10px;
  font-size: 19px; font-weight: 700; letter-spacing: -0.015em;
}
.pf-service p { margin: 0; color: var(--pf-muted, #5f6a7d); font-size: 15px; line-height: 1.65; }

.pf-project {
  display: flex; align-items: baseline; justify-content: space-between; gap: 18px;
  padding: 15px 0;
  border-bottom: 1px solid currentColor;
  text-decoration: none;
  color: inherit;
}
.pf-project:last-child { border-bottom: 0; }
.pf-project-t { font-size: 16px; font-weight: 600; }
.pf-project-m { font-size: 13px; color: var(--pf-muted, #5f6a7d); white-space: nowrap; }

.pf-stat { text-align: center; }
.pf-stat-n {
  display: block;
  font-size: clamp(34px, 4vw, 52px); font-weight: 800;
  letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums;
  color: var(--pf-accent, #4f46e5);
}
.pf-stat-l {
  display: block; margin-top: 8px;
  font-size: 13.5px; color: var(--pf-muted, #5f6a7d);
}

.pf-rule { border: 0; border-top: 1px solid currentColor; opacity: .2; margin: 0; }
.pf-spacer { width: 100%; }
.pf-embed > :first-child { margin-top: 0; }
.pf-embed > :last-child { margin-bottom: 0; }

/* ── header ─────────────────────────────────────────────────────────────── */
.pf-header { background: var(--pf-bg, #fff); border-bottom: 1px solid rgba(128,128,128,.14); }
.pf-header.is-sticky { position: sticky; top: 0; z-index: 30; backdrop-filter: saturate(1.4) blur(8px); }
.pf-header-in {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; padding-top: 16px; padding-bottom: 16px; flex-wrap: wrap;
}
.pf-brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
.pf-brand-logo { max-height: 40px; width: auto; object-fit: contain; }
.pf-brand-t {
  display: flex; flex-direction: column; gap: 1px;
  font-size: 17px; font-weight: 700; letter-spacing: -.015em; line-height: 1.2;
}
.pf-brand-t small { font-size: 12px; font-weight: 400; color: var(--pf-muted, #5f6a7d); letter-spacing: 0; }
.pf-nav { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.pf-nav a {
  font-size: 12.5px; font-weight: 600; text-decoration: none;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--pf-muted, #5f6a7d); transition: color .15s ease;
}
.pf-nav a:hover { color: var(--pf-accent, #4f46e5); }

/* ── header layouts ─────────────────────────────────────────────────────
   Four arrangements of the same two pieces. mark-left is the default and is
   what .pf-header-in already does, so it needs no rule of its own.

   "centred" is two rows on purpose. Centring the mark in a single row while
   keeping the menu beside it needs absolute positioning, which stops being
   centred the moment the menu wraps — and on a phone the menu always wraps. */
.pf-header--mark-right .pf-header-in { flex-direction: row-reverse; }

.pf-header--centred .pf-header-in {
  flex-direction: column; justify-content: center; gap: 12px;
}
.pf-header--centred .pf-brand { justify-content: center; }
.pf-header--centred .pf-nav { justify-content: center; }

/* "split" is the only one that genuinely needs three tracks, and it collapses
   to the centred stack below the width where two menus either side of a mark
   stop fitting. */
.pf-header--split .pf-header-in {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
}
.pf-header--split .pf-brand { justify-content: center; }
.pf-header--split .pf-nav-a { justify-content: flex-start; }
.pf-header--split .pf-nav-b { justify-content: flex-end; }

@media (max-width: 720px) {
  .pf-header--split .pf-header-in {
    display: flex; flex-direction: column; justify-content: center; gap: 12px;
  }
  .pf-header--split .pf-nav-a,
  .pf-header--split .pf-nav-b { justify-content: center; }
  .pf-header--mark-right .pf-header-in { flex-direction: column; }
}

/* ── gallery categories ─────────────────────────────────────────────────
   Filtering hides with a class rather than removing nodes, so the whole
   gallery is in the HTML for a search engine and for a visitor with no
   JavaScript. The buttons only appear when there are at least two
   categories — one category is a label, not a filter. */
.pf-cats {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px;
}
.pf-cat {
  font: inherit; font-size: 11.5px; font-weight: 650; line-height: 1;
  letter-spacing: .09em; text-transform: uppercase;
  padding: 10px 16px; border: 0; border-radius: 99px; cursor: pointer;
  background: var(--pf-surface, #f1f3f7); color: var(--pf-muted, #5f6a7d);
  transition: background .15s ease, color .15s ease;
}
.pf-cat:hover { color: var(--pf-text, #10141c); }
.pf-cat.is-on { background: var(--pf-accent, #4f46e5); color: #fff; }
.pf-gallery figure.is-off { display: none; }


/* ── price packages ─────────────────────────────────────────────────────── */
/* A hairline rather than a filled block. Three grey panels side by side is
   a pricing table from a software site; three ruled columns is a rate card,
   which is what a studio hands to a client. */
.pf-pk {
  display: flex; flex-direction: column; height: 100%;
  background: transparent;
  border: 1px solid rgba(128,128,128,.26);
  border-radius: var(--pf-radius, 14px);
  overflow: hidden;
}
/* The one being pushed reads differently without shouting. */
.pf-pk.is-featured {
  background: var(--pf-surface, #f6f7f9);
  border-color: transparent;
  outline: 2px solid var(--pf-accent, #4f46e5); outline-offset: -2px;
}
.pf-pk-img { margin: 0; }
.pf-pk-img img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.pf-pk-b { padding: 28px 26px 26px; display: flex; flex-direction: column; gap: 11px; flex: 1 1 auto; }
.pf-pk-tag {
  align-self: flex-start;
  padding: 4px 10px; border-radius: 999px;
  background: var(--pf-accent, #4f46e5); color: #fff;
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
}
.pf-pk-n { margin: 0; font-size: 19px; font-weight: 700; letter-spacing: -.015em; }
.pf-pk-p { margin: 0; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pf-pk-p span { font-size: clamp(26px, 3vw, 34px); font-weight: 800; letter-spacing: -.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.pf-pk-p small { font-size: 12.5px; color: var(--pf-muted, #5f6a7d); }
.pf-pk-d { margin: 0; font-size: 14px; line-height: 1.6; color: var(--pf-muted, #5f6a7d); }
.pf-pk-f { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pf-pk-f li {
  position: relative; padding-left: 21px;
  font-size: 14px; line-height: 1.55; color: var(--pf-muted, #5f6a7d);
}
.pf-pk-f li::before {
  content: ""; position: absolute; left: 2px; top: .52em;
  width: 9px; height: 5px; border-left: 2px solid var(--pf-accent, #4f46e5);
  border-bottom: 2px solid var(--pf-accent, #4f46e5); transform: rotate(-45deg);
}
.pf-pk-a { display: flex; gap: 8px; margin-top: auto; padding-top: 16px; flex-wrap: wrap; }
.pf-pk-a a {
  flex: 1 1 auto; text-align: center;
  padding: 12px 16px; border-radius: var(--pf-radius, 14px);
  font-size: 12px; font-weight: 650; letter-spacing: .08em; text-transform: uppercase;
  text-decoration: none;
  transition: opacity .15s ease;
}
.pf-pk-a a:hover { opacity: .88; }
.pf-pk-wa { background: #075e54; color: #fff; }
.pf-pk-tel { background: var(--pf-accent, #4f46e5); color: #fff; }

/* ── footer ─────────────────────────────────────────────────────────────── */
.pf-footer {
  background: var(--pf-surface, #f6f7f9);
  border-top: 1px solid rgba(128,128,128,.14);
  padding-top: 44px; padding-bottom: 34px;
  font-family: Inter, system-ui, sans-serif;
  color: var(--pf-muted, #5f6a7d);
}
.pf-footer-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 28px; flex-wrap: wrap;
  padding-bottom: 28px; margin-bottom: 22px;
  border-bottom: 1px solid rgba(128,128,128,.14);
}
.pf-footer-who { display: flex; flex-direction: column; gap: 7px; max-width: 320px; font-size: 13px; line-height: 1.6; }
.pf-footer-who strong { font-size: 15px; color: var(--pf-text, #101828); }
.pf-footer-links { display: flex; flex-direction: column; gap: 8px; }
.pf-footer-links a { font-size: 13px; text-decoration: none; color: var(--pf-muted, #5f6a7d); }
.pf-footer-links a:hover { color: var(--pf-accent, #4f46e5); }
/* The end of every portfolio, always in this order and always centred. */
.pf-footer-end {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  text-align: center; font-size: 12.5px;
}
.pf-copy { color: var(--pf-muted, #5f6a7d); }
/* Our line on every client portfolio. Quiet on purpose — smaller than the
   copyright above it — but quiet by size, not by fading it out of
   legibility. It follows the studio's own muted colour, so it sits inside
   their palette rather than fighting it. */
.pf-by { font-size: 11.5px; color: var(--pf-muted, #5f6a7d); }


/* ── narrower ───────────────────────────────────────────────────────────────
   Columns collapse in two steps rather than one: a 4-across row becomes two
   across on a tablet before it becomes one on a phone, which keeps a services
   row from turning into a very long list. */
@media (max-width: 900px) {
  .pf-row { gap: 26px; }
  .pf-col-1, .pf-col-2, .pf-col-3, .pf-col-4 { grid-column: span 6; }
  .pf-col-5, .pf-col-7, .pf-col-8 { grid-column: span 12; }
}
@media (max-width: 680px) {
  .pf-wrap { padding-left: 18px; padding-right: 18px; }
  .pf-row { gap: 22px; }
  .pf-col { grid-column: span 12 !important; }
  /* A template sets generous padding for a desktop — up to 150px — and on a
     phone that is most of a screen of nothing. Capped, not flattened: a
     section that declared no padding is left alone because the variable it
     would be capped through was never set. */
  .pf-section[style*="--pf-pt"] { padding-top: min(var(--pf-pt), 64px) !important; }
  .pf-section[style*="--pf-pb"] { padding-bottom: min(var(--pf-pb), 64px) !important; }
  .pf-btn { width: 100%; }
  .pf-gallery { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  /* A spacer exists to push a column down beside another one. With the
     columns stacked there is nothing to push past, so it is capped. */
  .pf-spacer { max-height: 32px; }
  .pf-contact { font-size: 17px; word-break: break-word; }
  .pf-project { flex-direction: column; gap: 4px; }
  .pf-project-m { white-space: normal; }
  .pf-footer { justify-content: center; text-align: center; padding-bottom: 34px; }
}
@media (max-width: 400px) {
  .pf-wrap { padding-left: 14px; padding-right: 14px; }
  .pf-quote { padding: 20px 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .pf-btn { transition: none; }
  .pf-btn:hover { transform: none; }
}

/* A printed portfolio is a portfolio someone liked enough to print. */
@media print {
  .pf-draft { display: none; }
  .pf-body { background: #fff; color: #000; }
  .pf-section { break-inside: avoid; }
}

/* ════════════════════════════════════════════════════════════════════════
   THE INSTRUCTION GUIDE

   Five steps that animate the action they describe. Drawn rather than
   recorded: a screen capture would be an order of magnitude heavier, would
   be wrong the first time a button moved, and could not be read aloud.

   Only the step on screen animates. The others are display:none, so nothing
   is being composited behind the panel, and each step restarts from its
   first frame every time it is opened.
   ════════════════════════════════════════════════════════════════════════ */

.pfg { position: fixed; inset: 0; z-index: 1200; display: grid; place-items: center; padding: 20px; }
.pfg[hidden] { display: none; }
.pfg-back { position: absolute; inset: 0; background: rgba(8, 10, 16, .62); backdrop-filter: blur(3px); }

.pfg-panel {
  position: relative;
  width: min(760px, 100%);
  max-height: min(92vh, 720px);
  display: flex;
  flex-direction: column;
  background: var(--card, #fff);
  color: var(--text, #111);
  border: 1px solid var(--border, #e5e7eb);
  border-radius: 16px;
  box-shadow: 0 24px 80px rgba(8, 10, 16, .35);
  overflow: hidden;
}
.pfg-panel:focus { outline: none; }

.pfg-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 22px 14px; }
.pfg-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--muted, #6b7280); }
.pfg-head h3 { margin: 4px 0 0; font-size: 19px; }
.pfg-x {
  flex-shrink: 0; width: 32px; height: 32px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--border, #e5e7eb); border-radius: 9px;
  color: inherit; cursor: pointer;
}
.pfg-x:hover { background: var(--hover, rgba(0, 0, 0, .04)); }

.pfg-rail { height: 3px; background: var(--border, #e5e7eb); }
.pfg-rail-fill { height: 100%; width: 20%; background: var(--primary, #4f46e5); transition: width .3s ease; }

.pfg-body { padding: 22px; overflow-y: auto; }

.pfg-step { display: none; }
.pfg-step.is-on { display: grid; gap: 20px; }

.pfg-art { background: var(--bg, #f7f8fa); border: 1px solid var(--border, #e5e7eb); border-radius: 12px; padding: 12px; }
.pfg-svg { display: block; width: 100%; height: auto; }
.pfg-text h4 { margin: 0 0 8px; font-size: 16px; }
.pfg-text p { margin: 0; font-size: 14px; line-height: 1.65; color: var(--muted, #6b7280); }

.pfg-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 22px; border-top: 1px solid var(--border, #e5e7eb);
}
.pfg-dots { display: flex; gap: 7px; }
.pfg-dot {
  width: 8px; height: 8px; padding: 0; border: 0; border-radius: 50%;
  background: var(--border-strong, #cbd5e1); cursor: pointer;
}
.pfg-dot.is-on { background: var(--primary, #4f46e5); }
.pfg-nav { display: flex; gap: 8px; }

@media (min-width: 720px) {
  .pfg-step.is-on { grid-template-columns: 1.15fr 1fr; align-items: center; }
}

/* ── the drawings ─────────────────────────────────────────────────────── */

.pfg-svg .g-card, .pfg-svg .g-frame { fill: var(--card, #fff); stroke: var(--border, #e5e7eb); stroke-width: 1.5; }
.pfg-svg .g-line { fill: var(--border, #e5e7eb); }
.pfg-svg .g-bar-in { fill: var(--bg, #f7f8fa); stroke: var(--border, #e5e7eb); stroke-width: 1.5; }
.pfg-svg text { font-family: inherit; font-size: 9px; font-weight: 600; text-anchor: middle; }

/* 1 · choosing a design */
.pfg-svg .g-pick { stroke: var(--primary, #4f46e5); stroke-width: 2; }
.is-on .g-pick { animation: g-pick 3.2s ease-in-out infinite; }
@keyframes g-pick { 0%, 30% { stroke: var(--border, #e5e7eb); stroke-width: 1.5; } 45%, 100% { stroke: var(--primary, #4f46e5); stroke-width: 2; } }

.pfg-svg .g-tick circle { fill: var(--primary, #4f46e5); }
.pfg-svg .g-tick path { fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.is-on .g-tick { transform-origin: 168px 34px; animation: g-pop 3.2s ease-in-out infinite; }
@keyframes g-pop { 0%, 34% { transform: scale(0); } 50%, 100% { transform: scale(1); } }

.pfg-svg .g-cursor { fill: var(--text, #111); }
.is-on .g-cursor { animation: g-move 3.2s ease-in-out infinite; }
@keyframes g-move {
  0% { transform: translate(210px, 110px); }
  30%, 100% { transform: translate(140px, 74px); }
}

/* 2 · editing */
.pfg-svg .g-drop { fill: none; stroke: var(--primary, #4f46e5); stroke-width: 1.5; stroke-dasharray: 5 4; }
.is-on .g-drop { animation: g-fade 3.6s ease-in-out infinite; }
@keyframes g-fade { 0%, 55% { opacity: 1; } 70%, 100% { opacity: 0; } }

.pfg-svg .g-drag rect { fill: var(--primary, #4f46e5); }
.pfg-svg .g-drag .g-drag-l { fill: #fff; opacity: .75; }
.is-on .g-drag { animation: g-drop 3.6s ease-in-out infinite; }
@keyframes g-drop {
  0% { transform: translate(180px, 108px); }
  55%, 100% { transform: translate(105px, 52px); }
}

.pfg-svg .g-type { fill: var(--text, #111); opacity: .75; }
.is-on .g-type { animation: g-type 3.6s steps(14) infinite; }
@keyframes g-type { 0%, 62% { width: 0; } 92%, 100% { width: 150px; } }
.is-on .g-caret { animation: g-caret 3.6s infinite; }
@keyframes g-caret {
  0%, 60% { opacity: 0; transform: translateX(0); }
  62% { opacity: 1; }
  92%, 100% { opacity: 1; transform: translateX(150px); }
}

/* 3 · pictures */
.pfg-svg .g-photo rect { fill: var(--border, #e5e7eb); }
.is-on .g-photo { animation: g-in .5s ease-out both; animation-delay: calc(var(--i) * .22s); }
@keyframes g-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.pfg-svg .g-bar-bg { fill: var(--border, #e5e7eb); }
.pfg-svg .g-bar { fill: var(--primary, #4f46e5); }
.is-on .g-bar { animation: g-fill 3s ease-in-out infinite; }
@keyframes g-fill { 0% { width: 0; } 70%, 100% { width: 68px; } }

/* 4 · the address — the studio name is the FIRST thing in it */
.pfg-svg .g-lock rect { fill: #16a34a; }
.pfg-svg .g-lock path { fill: none; stroke: #16a34a; stroke-width: 1.6; }
.pfg-svg .g-url { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; text-anchor: start; }
.pfg-svg .g-url-name { fill: var(--primary, #4f46e5); font-weight: 700; }
.pfg-svg .g-url-rest { fill: var(--muted, #6b7280); }
.pfg-svg .g-underline { fill: var(--primary, #4f46e5); }
.is-on .g-underline { transform-origin: 60px 84px; animation: g-underline 3.4s ease-in-out infinite; }
@keyframes g-underline { 0%, 20% { transform: scaleX(0); } 45%, 100% { transform: scaleX(1); } }
.is-on .g-url-name { animation: g-glow 3.4s ease-in-out infinite; }
@keyframes g-glow { 0%, 20% { opacity: .35; } 45%, 100% { opacity: 1; } }

/* 5 · sharing the link
   The badge used to swap from Draft to Live, because a page had to be
   published before it had a link. It is live when the account is made, so
   there is no swap to animate and nothing here is ever in a draft state. */
.pfg-svg .g-badge-live rect { fill: #16a34a; }
.pfg-svg .g-badge text { fill: #fff; }

.pfg-svg .g-copy rect { fill: var(--primary, #4f46e5); }
.pfg-svg .g-copy text { fill: #fff; }
.is-on .g-copy { transform-origin: 230px 79px; animation: g-press 4s ease-in-out infinite; }
@keyframes g-press { 0%, 55% { transform: scale(1); } 62% { transform: scale(.92); } 70%, 100% { transform: scale(1); } }

.pfg-svg .g-copied rect { fill: var(--text, #111); }
.pfg-svg .g-copied text { fill: #fff; }
.pfg-svg .g-copied { opacity: 0; }
.is-on .g-copied { animation: g-copied 4s ease-in-out infinite; }
@keyframes g-copied { 0%, 60% { opacity: 0; } 70%, 90% { opacity: 1; } 100% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .pfg-svg * { animation: none !important; }
  /* The state each animation ENDS on is the one that explains the step, so a
     still has to show the finished state, never the starting one. */
  .pfg-svg .g-copied { opacity: 1; }
  .pfg-svg .g-type { width: 150px; }
}
