@charset "UTF-8";
@layer reset, wp, base, components, panda, overrides;
@layer wp.core, wp.global, wp.plugins, wp.supports;
/* Frontend entry point (compiled by tools/postcss.ts → frontend.css).
 *
 * Import order matters:
 *   _layers   — emits the `@layer …;` order decl (must be first)
 *   _globals  — @custom-media + @define-mixin defs (emit no CSS; needed by
 *               every partial below before custom-media/mixins resolve)
 *   _assembled_root / _fe / _f — generated by tools/assemble.ts (one @import
 *               per source partial, alpha-sorted = load order)
 *
 * postcss-import inlines all of the above; the remaining rule(s) below are
 * authored inline. @import statements MUST stay at the top (CSS requirement).
 */
/* Cascade layer order declaration.
 *
 * Imported first (right after any @charset) by the entry files so this
 * declaration lands at the top of the compiled output, establishing the
 * canonical layer order BEFORE any source file's @layer block is encountered
 * (a CSS requirement). See theme/docs/cascade-layers.md.
 *
 * Layer order, lowest → highest precedence.
 *
 * `wp` is split into sub-layers by source (see 70-php/css-layers): WP/plugin CSS
 * is wrapped into wp.core / wp.global / wp.plugins / wp.supports instead of a
 * single bucket, so their precedence is explicit. Reorder the 2nd line to tune
 * who wins among WordPress sources (e.g. move wp.plugins above wp.global to let
 * gutenx block CSS beat theme.json globals). Theme layers (base/components/
 * panda/overrides) still sit above all of wp; reset sits below it. */
/* Theme-wide PostCSS authoring primitives.
 *
 * Imported FIRST by the entry files (assets/css/frontend.pcss, the editor
 * stages) so postcss-import inlines these definitions ahead of every source
 * partial. The definitions emit no CSS themselves:
 *   - @custom-media is consumed + removed by postcss-custom-media
 *   - @define-mixin is consumed + removed by postcss-mixins
 *
 * Replaces the old Sass globals (_globals.scss → typo mixins, $breakpoints
 * map, fluid()/rem()/round() functions). The `fluid()` function is now a
 * build-time PostCSS plugin (tools/postcss/fluid.ts), not declared here.
 *
 * What this provides:
 *   custom media:  --to-xs-sm / --to-navi / --to-md / --to-md-lg / --to-lg
 *                  --lt-md / --from-navi / --from-xl
 *                  --navi-to-lg / --md-to-lg / --lg-to-xl
 *   mixins:        typo, typo_important, typo_important_all
 */
/* --- Breakpoints (single source of truth) -------------------------------- */
/* Each body is written to match the exact media-query string dart-sass used
 * to emit from `map-get($breakpoints, X)`, so output stays byte-identical.
 * Scale (rem): xs-sm 30 · navi/md 48 · md-lg 56.25 · lg 64 · xl 80. */
/* max-width (`@media (max-width: …)`) */
/* mega-nav → hamburger only on real tablet/phone (<768px). Its desktop row (logo 251 + menu ≈763) fits ≥1134px and WRAPS gracefully to 2 rows below that — it never overflows — so keep this at 48rem. Do NOT hike it toward ~72–75rem: that shows the hamburger on ordinary <1200px desktop windows and the ~1000px editor canvas. */
/* range-syntax single edge */
/* range-syntax both edges */
/* --- Typography mixins ---------------------------------------------------- */
/* Faithful port of theme/00-design-system/00-typo/_root.scss. Each reads the
 * per-level custom properties (--<level>-fs etc.). Declaration order is kept
 * identical to the Sass mixins for output parity. */
/* Typography roots: font-family + weight custom properties. The typo() mixin
 * family that used to live here now
 * lives in theme/_globals.pcss as @define-mixin (imported by the entry files).
 * The old Sass typo vars are inlined at their call sites as `buttons`. */
:root {
  --display-ff: geist-mono, monospace;
  --body-ff: geist-mono, monospace;

  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-display: 900;
}
@layer base {
:root{
  /* copy */
  --copy-ff: var(--body-ff);
  --copy-fs: 0.78rem;
  --wp-preset-font-size-copy: var(--copy-fs) !important;
  --copy-ls: 0rem;
  --copy-lh: 1.48rem;
  --copy-fw: 400;
  /* name */
  --name-ff: var(--body-ff);
  --name-fs: 1rem;
  --wp-preset-font-size-name: var(--name-fs) !important;
  --name-ls: 0rem;
  --name-lh: 1.45rem;
  --name-fw: 400;
  /* label */
  --label-ff: var(--body-ff);
  --label-fs: 0.75rem;
  --wp-preset-font-size-label: var(--label-fs) !important;
  --label-ls: 0rem;
  --label-lh: 1.09rem;
  --label-fw: 400;
  /* meta */
  --meta-ff: var(--body-ff);
  --meta-fs: 0.75rem;
  --wp-preset-font-size-meta: var(--meta-fs) !important;
  --meta-ls: 0rem;
  --meta-lh: 1.27rem;
  --meta-fw: 400;
  /* list */
  --list-ff: var(--body-ff);
  --list-fs: 0.75rem;
  --wp-preset-font-size-list: var(--list-fs) !important;
  --list-ls: 0rem;
  --list-lh: 1.58rem;
  --list-fw: 400;
  /* cap */
  --cap-ff: var(--body-ff);
  --cap-fs: 0.69rem;
  --wp-preset-font-size-cap: var(--cap-fs) !important;
  --cap-ls: 0rem;
  --cap-lh: 1rem;
  --cap-fw: 400;
  /* cap-list */
  --cap-list-ff: var(--body-ff);
  --cap-list-fs: 0.69rem;
  --wp-preset-font-size-cap-list: var(--cap-list-fs) !important;
  --cap-list-ls: 0rem;
  --cap-list-lh: 1.38rem;
  --cap-list-fw: 400;
  /* title */
  --title-ff: var(--body-ff);
  --title-fs: 1.13rem;
  --wp-preset-font-size-title: var(--title-fs) !important;
  --title-ls: 0rem;
  --title-lh: 1.58rem;
  --title-fw: 400;
}
}
@layer base {
:root {
  --c-paper: #fefefe;

  --c-ink: #111111;

  --c-ink-soft: #333333;

  --c-muted: #999999;

  --c-muted-2: #767676;

  --c-faint: #666666;

  --c-hairline: #e9e9e7;

}

}
/* Fluid spacing scale + line-height helpers.
 *
 * Was a Sass `@each` over a $spacings map calling fluid(); now the scale is
 * written out explicitly in the SAME order (4,12,16,24,44,48,72,96,144,132)
 * with literal fluid() calls. The fluid() function is resolved at build time
 * by tools/postcss/fluid.ts → clamp(). (from, to) pairs are preserved exactly. */
@layer base {
  :root {
    --s4: 4px;
    --s8: 8px;
    --s12: clamp(0.5rem, 1.04vw + 0.08rem, 0.75rem);
    --s16: clamp(0.75rem, 1.04vw + 0.33rem, 1rem);
    --s24: clamp(1rem, 2.08vw + 0.17rem, 1.5rem);
    --s32: clamp(1.25rem, 3.13vw + 0rem, 2rem);
    --s44: clamp(1.5rem, 5.21vw + -0.58rem, 2.75rem);
    --s48: clamp(1.5rem, 6.25vw + -1rem, 3rem);
    --s64: clamp(2rem, 8.33vw + -1.33rem, 4rem);
    --s72: clamp(3rem, 6.25vw + 0.5rem, 4.5rem);
    --s96: clamp(3rem, 12.5vw + -2rem, 6rem);
    --s144: clamp(4rem, 20.83vw + -4.33rem, 9rem);
    --s132: clamp(6rem, 9.38vw + 2.25rem, 8.25rem);
    --rlh: var(--copy-lh);

    --lh: var(--rlh);
    --lh-half: calc(0.5 * var(--rlh));
    --lh-single: var(--rlh);
    --lh-double: calc(2 * var(--rlh));
    --lh-quadruple: calc(4 * var(--rlh));
  }
    @supports (width: 1rlh) {
  :root {
      --rlh: 1rlh;
  }
    }

  .mt-single {
    margin-top: var(--lh-single) !important;
  }
  .mt-double {
    margin-top: var(--lh-double) !important;
  }
  .mt-quadruple {
    margin-top: var(--lh-quadruple) !important;
  }
}
@layer base {
:root {
  /* Standard durations. Off-scale values (140ms, 180ms, 220ms) intentionally */
  /* stay as literals at their callsites because they were tuned to feel right */
  /* for a specific interaction (spur grid, focus ring). */
  --duration-fast: 100ms;
  --duration-base: 200ms;
  --duration-slow: 300ms;

  --ease: ease;
  --ease-in: ease-in;
  --ease-out: ease-out;
  --ease-in-out: ease-in-out;
}
}
@layer base {
:root {
  /* Cascade: each step is ~×2 the previous bucket so values stay legible */
  /* and there's room to slot new components in without renumbering. */
  --z-base: 0;
  --z-lifted: 1;
  --z-stacked: 2;
  --z-dropdown: 20;
  --z-header: 50;
  --z-sticky: 100;
  --z-modal: 200;
  --z-mobile-menu: 300;
}
}
/* gutenx plugin contract — aliases only.
 * Maps every --var the gutenx frontend-purified CSS references to the
 * mehdi semantic token set. Never add design decisions here; this file
 * exists solely so the plugin renders without undefined vars.
 * Source: grep 'var(--' gutenx/assets/frontend-purified.min.css
 */
@layer base {
:root {

  /* ── Color: canonical names → semantic slugs ─────────────────────── */
  --c-black:    var(--c-ink);
  --c-white:    #ffffff;           /* literal white (not paper) for overlays */
  --c-darkgrey: var(--c-ink-soft);
  --c-green:    var(--c-muted);    /* comm2 lie-name was #999 = muted */
  --c-cinnamon: var(--c-muted-2);  /* comm2 lie-name was #767 = muted-2 */
  --c-lila:     var(--c-hairline); /* comm2 lie-name was #e9e9e7 = hairline */
  --c-grey:     var(--c-muted);
  --c-main-10:  var(--c-ink);      /* plugin hover colour → ink */
  --c-main-20:  var(--c-ink-soft);
  --c-main-40:  var(--c-muted);

  /* ── Internal UI shades + overlays (not in colors.json on purpose) ─ */
  --c-ui-grey-100: #ddd;
  --c-ui-grey-500: #757575;
  --c-overlay-10:  rgba(0, 0, 0, 0.1);
  --c-overlay-20:  rgba(0, 0, 0, 0.2);
  --c-overlay-60:  rgba(0, 0, 0, 0.6);

  /* ── UI component colour aliases ───────────────────────────────────── */
  --c-ui-bg:      var(--c-paper);
  --c-ui-fg:      var(--c-ink);
  --c-ui-surface: #ffffff;
  --c-ui-border:  var(--c-ink);
  --c-ui-shadow:  #ffffff;

  /* ── Shorthand aliases (--black / --white / --fg / --bg) ───────────── */
  --black:       var(--c-ink);
  --black-hover: var(--c-ink);
  --white:       #ffffff;
  --white-hover: #ffffff;

  --fg:       var(--c-ink);
  --fg-hover: var(--c-ink);
  --bg:       var(--c-paper);
  --bg-hover: var(--c-paper);

  /* ── Primary ────────────────────────────────────────────────────────── */
  --primary: var(--wp-admin-theme-color, var(--c-ink));

  /* ── Button tokens ──────────────────────────────────────────────────── */
  --button-bg:          var(--c-ink);
  --button-bg-hover:    var(--c-ink);
  --button-text:        var(--c-paper);
  --button-text-hover:  var(--c-paper);
  --button-border-color: var(--c-ink);

  /* ── Link tokens ────────────────────────────────────────────────────── */
  --text-link-text:  currentColor;
  --text-link-hover: var(--c-ink);
  --ui-link-text:    currentColor;
  --ui-link-hover:   var(--c-ink);

  /* ── Typography: comm2 token names → mehdi label/name vars ─────────── */
  /* Plugin blocks that rendered comm2 tokens need a fallback to something
   * legible. These are never used in 40-panda — component CSS uses
   * @include typo() directly. */
  --tm-ff: var(--body-ff);
  --tm-fs: var(--label-fs, 0.75rem);
  --tm-fw: var(--fw-medium, 500);
  --tm-lh: var(--label-lh, 1.45);
  --tm-ls: 0;

  --ts-ff: var(--body-ff);
  --ts-fs: var(--label-fs, 0.75rem);
  --ts-fw: var(--fw-medium, 500);
  --ts-lh: var(--label-lh, 1.45);
  --ts-ls: 0;

  --navi-ff: var(--body-ff);
  --navi-fs: var(--label-fs, 0.75rem);
  --navi-fw: var(--fw-medium, 500);
  --navi-lh: var(--label-lh, 1.45);
  --navi-ls: 0;

  --dachzeile-ff: var(--body-ff);
  --dachzeile-fs: var(--cap-fs, 0.6875rem);
  --dachzeile-fw: 400;
  --dachzeile-lh: var(--cap-lh, 1.4);
  --dachzeile-ls: 0;

  --quote-ff:      var(--body-ff);
  --quote-fs:      var(--name-fs, 1rem);
  --quote-fw:      400;
  --quote-lh:      var(--name-lh, 1.45);
  --quote-ls:      0;
  --quote-mark-fs: var(--name-fs, 1rem);
  --quote-mark-lh: var(--name-lh, 1.45);

  --footer-header-ff: var(--body-ff);
  --footer-header-fs: var(--cap-fs, 0.6875rem);
  --footer-header-fw: 400;
  --footer-header-lh: var(--cap-lh, 1.4);
  --footer-header-ls: 0;

  --h1-ff: var(--body-ff);
  --h1-fs: var(--title-fs, 1.125rem);
  --h1-fw: 400;
  --h1-lh: var(--title-lh, 1.4);
  --h1-ls: 0;

  --h2-ff: var(--body-ff);
  --h2-fs: var(--title-fs, 1.125rem);
  --h2-fw: 400;
  --h2-lh: var(--title-lh, 1.4);
  --h2-ls: 0;

  --buttons-ff: var(--body-ff);
  --buttons-fs: var(--label-fs, 0.75rem);
  --buttons-fw: 400;
  --buttons-lh: var(--label-lh, 1.45);
  --buttons-ls: 0;

  /* ── Misc plugin vars ───────────────────────────────────────────────── */
  --hr-color: var(--c-hairline);
  --hov-transition: color 0.15s ease, background-color 0.15s ease;

}
}
/* Portfolio layout tokens.
 * Font sizes + colors live in 00-design-system/ (type-sizes.yaml → @mixin typo,
 * colors.json → --c-*) and are consumed directly in _fe.pcss — never redefined
 * here. This file carries only the site's layout geometry. */
:root {
  --ph-gap: 26px;                   /* column gutter */
  --ph-pad-x: 31px;                 /* frame inset */
  --ph-sidebar-w: 260px;            /* sticky sidebar width */
}
@layer base {
:where(p, .copy, .has-copy-font-size), :is(.has-copy-font-size > p , .is-style-view-as-copy, .is-style-view-as-copy  *){
  font-size: var(--copy-fs);
  line-height: var(--copy-lh);
  font-weight: var(--copy-fw);
  letter-spacing: var(--copy-ls);
  font-family: var(--copy-ff);
}
:where(.name, .has-name-font-size), :is(.has-name-font-size > p , .is-style-view-as-name, .is-style-view-as-name  *){
  font-size: var(--name-fs);
  line-height: var(--name-lh);
  font-weight: var(--name-fw);
  letter-spacing: var(--name-ls);
  font-family: var(--name-ff);
}
:where(.label, .has-label-font-size), :is(.has-label-font-size > p , .is-style-view-as-label, .is-style-view-as-label  *){
  font-size: var(--label-fs);
  line-height: var(--label-lh);
  font-weight: var(--label-fw);
  letter-spacing: var(--label-ls);
  font-family: var(--label-ff);
}
:where(.meta, .has-meta-font-size), :is(.has-meta-font-size > p , .is-style-view-as-meta, .is-style-view-as-meta  *){
  font-size: var(--meta-fs);
  line-height: var(--meta-lh);
  font-weight: var(--meta-fw);
  letter-spacing: var(--meta-ls);
  font-family: var(--meta-ff);
}
:where(.list, .has-list-font-size), :is(.has-list-font-size > p , .is-style-view-as-list, .is-style-view-as-list  *){
  font-size: var(--list-fs);
  line-height: var(--list-lh);
  font-weight: var(--list-fw);
  letter-spacing: var(--list-ls);
  font-family: var(--list-ff);
}
:where(.cap, .has-cap-font-size), :is(.has-cap-font-size > p , .is-style-view-as-cap, .is-style-view-as-cap  *){
  font-size: var(--cap-fs);
  line-height: var(--cap-lh);
  font-weight: var(--cap-fw);
  letter-spacing: var(--cap-ls);
  font-family: var(--cap-ff);
}
:where(.cap-list, .has-cap-list-font-size), :is(.has-cap-list-font-size > p , .is-style-view-as-cap-list, .is-style-view-as-cap-list  *){
  font-size: var(--cap-list-fs);
  line-height: var(--cap-list-lh);
  font-weight: var(--cap-list-fw);
  letter-spacing: var(--cap-list-ls);
  font-family: var(--cap-list-ff);
}
:where(h1, h2, h3, .title, .has-title-font-size), :is(.has-title-font-size > p , .is-style-view-as-title, .is-style-view-as-title  *){
  font-size: var(--title-fs);
  line-height: var(--title-lh);
  font-weight: var(--title-fw);
  letter-spacing: var(--title-ls);
  font-family: var(--title-ff);
}
}
@layer base {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  * {
    margin: 0;
  }

  body {
    background-color: var(--c-paper);
    color: var(--c-ink);
  }

  img,
  video,
  svg {
    display: block;
    max-inline-size: 100%;
    height: auto;
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  input,
  button,
  textarea,
  select {
    font: inherit;
  }

  :focus-visible {
    outline: 2px solid var(--c-ink);
    outline-offset: 2px;
  }
}
/* ============================================================================
 * Mehdi Moradpour — photography portfolio. Frontend layout + views.
 * 1:1 from Portfolio.dc.html (desktop). Mobile collapse is INVENTED (the design
 * has no mobile spec) — kept minimal + obvious: sidebar → top bar, grids → 1-col.
 *
 * Font sizes + line-heights come from @mixin typo <token> (00-design-system/
 * type-sizes.yaml); colors from --c-* (colors.json). Uppercase + 0.02em tracking
 * stay in component CSS (the token generator can't express em tracking).
 * ==========================================================================*/
@layer panda {

  /* --- shared type helpers -------------------------------------------------*/
  .ph-label {              /* section labels: "Works in Series" etc. */
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--c-muted);
  }
  .ph-cap {                /* image captions + counters */
    --_lh: var(--cap-lh);
    font-size: var(--cap-fs);
    font-weight: var(--cap-fw);
    line-height: var(--cap-lh);
    letter-spacing: var(--cap-ls);
    font-family: var(--cap-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--c-muted);
    padding-top: 10px;
  }

  /* --- shell: sticky sidebar + main ---------------------------------------*/
  .ph-shell {
    display: flex;
    align-items: stretch;
    min-height: 100vh;
    background: var(--c-paper);
  }

  /* The sidebar ships as a template part, so WP wraps it in a
   * `<div.wp-block-template-part>`. That wrapper — not `.ph-sidebar` — is the
   * flex child of `.ph-shell`, and with no flex-basis it collapses to the nav's
   * content width (~193px). Remove the wrapper box so `.ph-sidebar` (with its
   * `flex:0 0 260px`, `order:-1`, sticky, `height:100vh`) is the direct flex
   * child again — matching the design DOM exactly. */
  .ph-shell > .wp-block-template-part { display: contents; }

  .ph-sidebar {
    order: -1;
    flex: 0 0 var(--ph-sidebar-w);
    padding: 30px 18px 14px var(--ph-pad-x);
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    letter-spacing: 0.02em;
    text-transform: uppercase;
  }
  .ph-sidebar__name {
    --_lh: var(--name-lh);
    font-size: var(--name-fs);
    font-weight: var(--name-fw);
    line-height: var(--name-lh);
    letter-spacing: var(--name-ls);
    font-family: var(--name-ff);
    text-transform: none;
    text-decoration: underline;
    text-underline-offset: 2px;
    color: var(--c-ink);
  }
  .ph-sidebar__nav {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    margin-top: 106px;
  }
  /* Nav items are wp:paragraph (<p.wp-block-paragraph>). WP `@layer wp.core`
   * sets font-size/line-height DIRECTLY on `.wp-block-paragraph` (the copy token,
   * 12.48/23.68 → 32px pitch), beating the `label` typo the container only
   * supplies by INHERITANCE. Re-apply the token directly on the <p> so it wins,
   * with line-height:normal (design renders 12px / lh-normal → 24px pitch) — same
   * override shape as the CV rows below. Re-assert uppercase + 0.02em because the
   * mixin emits `letter-spacing: var(--label-ls)` (=0), which would otherwise zero
   * the tracking the container supplied by inheritance. */
  .ph-sidebar__nav p,
  .ph-home__nav p {
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    line-height: normal;
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }
  .ph-sidebar__nav a {
    color: var(--c-ink);
    text-decoration: none;
  }
  .ph-sidebar__nav a:hover,
  .ph-sidebar__nav a[aria-current] {
    text-decoration: underline;
    text-underline-offset: 2px;
  }

  .ph-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    padding: 30px var(--ph-pad-x) 14px 0;
  }

  .ph-footer {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    --_lh: var(--cap-lh);
    font-size: var(--cap-fs);
    font-weight: var(--cap-fw);
    line-height: var(--cap-lh);
    letter-spacing: var(--cap-ls);
    font-family: var(--cap-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding-top: 26px;
    margin-top: auto;
  }

  /* --- 404 note ------------------------------------------------------------*/
  .ph-note {
    --_lh: var(--copy-lh);
    font-size: var(--copy-fs);
    font-weight: var(--copy-fw);
    line-height: var(--copy-lh);
    letter-spacing: var(--copy-ls);
    font-family: var(--copy-ff);
    color: var(--c-ink-soft);
    max-width: 520px;
    padding-top: 24px;
  }
  .ph-note a { text-decoration: underline; }

  /* --- Works index: irregular 12-col mosaic --------------------------------*/
  .ph-works .ph-label { padding-bottom: 60px; }

  .ph-mosaic {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    -moz-column-gap: var(--ph-gap);
         column-gap: var(--ph-gap);
    row-gap: 90px;
    align-items: start;
    padding-bottom: 140px;
  }
  .ph-series { cursor: pointer; }
  .ph-series img {
    width: 100%;
    display: block;
    transition: opacity 0.2s ease;
  }
  .ph-series:hover img { opacity: 0.72; }
  .ph-series__meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 2px 18px;
    --_lh: var(--cap-lh);
    font-size: var(--cap-fs);
    font-weight: var(--cap-fw);
    line-height: var(--cap-lh);
    letter-spacing: var(--cap-ls);
    font-family: var(--cap-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding-top: 10px;
  }
  .ph-series__meta .count { color: var(--c-muted); white-space: nowrap; }
  .ph-series__meta .title {
    /* re-assert cap type: the `title` token emits a global `.title` utility
     * (:where h1,h2,h3,.title …) that would otherwise blow this up to 18px */
    --_lh: var(--cap-lh);
    font-size: var(--cap-fs);
    font-weight: var(--cap-fw);
    line-height: var(--cap-lh);
    letter-spacing: var(--cap-ls);
    font-family: var(--cap-ff);
    letter-spacing: 0.02em;
    white-space: nowrap;
  }

  /* irregular editorial rhythm — [start / span / top-offset], cycles every 10.
   * Faithful to the design's `cells` array (index % 10). */
  .ph-mosaic > *:nth-child(10n+1)  { grid-column: 1 / span 9;  margin-top: 0; }
  .ph-mosaic > *:nth-child(10n+2)  { grid-column: 9 / span 4;  margin-top: 200px; }
  .ph-mosaic > *:nth-child(10n+3)  { grid-column: 1 / span 4;  margin-top: 80px; }
  .ph-mosaic > *:nth-child(10n+4)  { grid-column: 6 / span 7;  margin-top: 180px; }
  .ph-mosaic > *:nth-child(10n+5)  { grid-column: 1 / span 5;  margin-top: 0; }
  .ph-mosaic > *:nth-child(10n+6)  { grid-column: 7 / span 6;  margin-top: 240px; }
  .ph-mosaic > *:nth-child(10n+7)  { grid-column: 2 / span 10; margin-top: 120px; }
  .ph-mosaic > *:nth-child(10n+8)  { grid-column: 1 / span 4;  margin-top: 60px; }
  .ph-mosaic > *:nth-child(10n+9)  { grid-column: 6 / span 4;  margin-top: 200px; }
  .ph-mosaic > *:nth-child(10n+10) { grid-column: 8 / span 5;  margin-top: 0; }

  /* --- mobile collapse (INVENTED — no design spec) -------------------------*/
  @media (max-width: 48rem) {
    .ph-shell { flex-direction: column; min-height: 0; }
    .ph-sidebar {
      order: 0;
      flex: none;
      position: static;
      height: auto;
      width: 100%;
      flex-direction: row;
      align-items: baseline;
      justify-content: space-between;
      gap: 20px;
      padding: 20px var(--ph-pad-x);
    }
    .ph-sidebar__nav {
      flex-direction: row;
      flex-wrap: wrap;
      gap: 6px 16px;
      margin-top: 0;
    }
    .ph-main { padding: 8px var(--ph-pad-x) 24px; }
    .ph-mosaic {
      grid-template-columns: 1fr;
      row-gap: 40px;
      padding-bottom: 60px;
    }
    .ph-mosaic > * { grid-column: 1 / -1 !important; margin-top: 0 !important; }
  }
}
/* ============================================================================
 * Mehdi Moradpour — per-view layout (home, series detail, portraits, books,
 * CV, contact). 1:1 from Portfolio.dc.html (desktop). Shared chrome + works
 * mosaic live above. Mobile collapse is INVENTED (design is desktop-only).
 * ==========================================================================*/
@layer panda {

  /* --- HOME: full-bleed cover + overlaid name & nav ------------------------*/
  .ph-home {
    position: relative;
    height: 100vh;
    background: var(--c-paper);
    overflow: hidden;
  }
  .ph-home > figure {          /* cover figure (wp:image, internally linked) — fills the frame */
    position: absolute;
    inset: 0;
    margin: 0;
    cursor: pointer;
  }
  .ph-home > figure,
  .ph-home > figure a {
    display: block;
    width: 100%;
    height: 100%;
  }
  .ph-home figure img {
    width: 100%;
    height: 100%;
    -o-object-fit: cover;
       object-fit: cover;
    display: block;
  }
  .ph-home__name {
    z-index: 2;
    position: absolute;
    left: var(--ph-pad-x);
    top: 30px;
    --_lh: var(--name-lh);
    font-size: var(--name-fs);
    font-weight: var(--name-fw);
    line-height: var(--name-lh);
    letter-spacing: var(--name-ls);
    font-family: var(--name-ff);
    color: var(--c-ink);
    text-decoration: underline;
    text-underline-offset: 2px;
  }
  .ph-home__nav {
    z-index: 2;
    position: absolute;
    left: 101px;
    top: 159px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    letter-spacing: 0.02em;
    text-transform: uppercase;
  }
  .ph-home__nav a { color: var(--c-muted-2); text-decoration: none; }
  .ph-home__nav a:hover { text-decoration: underline; text-underline-offset: 2px; }

  /* --- image rows shared by series-detail + portraits ----------------------*/
  .ph-plates { display: flex; flex-direction: column; gap: 60px; }
  .ph-plate--full img { width: 100%; height: auto; display: block; }
  .ph-plate--pair {
    display: flex;
    gap: var(--ph-gap);
    align-items: flex-start;
  }
  .ph-plate--pair > * {
    flex: 1 1 0;            /* JS overrides flex-grow with the image aspect ratio */
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
  }
  .ph-plate--pair img { width: 100%; height: auto; display: block; }

  /* --- SERIES DETAIL -------------------------------------------------------*/
  .ph-series-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--c-muted);
    padding-bottom: 26px;
  }
  .ph-series-head a { color: var(--c-muted); }
  /* index removed → title + meta fill the header row, spread apart, baseline-aligned */
  .ph-series-head__right { display: flex; flex: 1; justify-content: space-between; align-items: baseline; gap: 20px; }
  .ph-series-head__title { color: var(--c-ink); }

  .ph-statement {
    display: flex;
    gap: var(--ph-gap);
    border-top: 1px solid var(--c-hairline);
    margin-top: 100px;
    padding: 44px 0 60px;
  }
  .ph-statement__meta {
    flex: 0 0 240px;
    --_lh: var(--meta-lh);
    font-size: var(--meta-fs);
    font-weight: var(--meta-fw);
    line-height: var(--meta-lh);
    letter-spacing: var(--meta-ls);
    font-family: var(--meta-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }
  .ph-statement__meta .sub { color: var(--c-muted); }
  .ph-statement__body {
    flex: 1;
    max-width: 640px;
    --_lh: var(--copy-lh);
    font-size: var(--copy-fs);
    font-weight: var(--copy-fw);
    line-height: var(--copy-lh);
    letter-spacing: var(--copy-ls);
    font-family: var(--copy-ff);
    color: var(--c-ink-soft);
  }
  .ph-statement__body p { margin: 0 0 16px; }
  .ph-statement__body p.sign { margin: 0; color: var(--c-muted); }

  .ph-series-detail { padding-bottom: 40px; }

  /* --- PORTRAITS -----------------------------------------------------------*/
  .ph-portraits { padding-bottom: 120px; }
  .ph-portraits .ph-label { padding-bottom: 26px; }
  .ph-portraits .ph-plates { gap: 60px; }

  /* --- BOOKS ---------------------------------------------------------------*/
  .ph-books {
    display: flex;
    flex-direction: column;
    gap: 100px;
    padding-bottom: 120px;
  }
  .ph-book {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 26px 40px;
    align-items: start;
  }
  .ph-book + .ph-book {
    border-top: 1px solid var(--c-hairline);
    padding-top: 100px;
  }
  .ph-book__img {
    max-width: 420px;
    cursor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNCIgaGVpZ2h0PSIzNCI+PHBhdGggZD0iTTEyIDggTDIxIDE3IEwxMiAyNiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMTExIiBzdHJva2Utd2lkdGg9IjEuNSIvPjwvc3ZnPg==) 17 17, e-resize;
  }
  .ph-book__img img { width: 100%; display: block; }
  .ph-book__side { max-width: 520px; }
  .ph-book__eyebrow {
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
    color: var(--c-muted); padding-bottom: 20px;
  }
  .ph-book__title {
    --_lh: var(--title-lh);
    font-size: var(--title-fs);
    font-weight: var(--title-fw);
    line-height: var(--title-lh);
    letter-spacing: var(--title-ls);
    font-family: var(--title-ff);
    text-transform: uppercase;
    padding-bottom: 20px;
  }
  .ph-book__body { --_lh: var(--copy-lh); font-size: var(--copy-fs); font-weight: var(--copy-fw); line-height: var(--copy-lh); letter-spacing: var(--copy-ls); font-family: var(--copy-ff); color: var(--c-ink-soft); }
  .ph-book__body p { margin: 0 0 16px; }
  .ph-book__body p:last-child { margin-bottom: 24px; }
  .ph-book__meta {
    --_lh: var(--cap-list-lh);
    font-size: var(--cap-list-fs);
    font-weight: var(--cap-list-fw);
    line-height: var(--cap-list-lh);
    letter-spacing: var(--cap-list-ls);
    font-family: var(--cap-list-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
    color: var(--c-faint); padding-bottom: 28px;
  }
  /* CTA: className lands on the .wp-block-button wrapper; style the inner link
   * and strip WP-core button chrome (bg/radius/font). */
  .ph-book__cta { display: inline-block; }
  .ph-book__cta .wp-block-button__link {
    display: inline-block;
    --_lh: var(--cap-lh);
    font-size: var(--cap-fs);
    font-weight: var(--cap-fw);
    line-height: var(--cap-lh);
    letter-spacing: var(--cap-ls);
    font-family: var(--cap-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
    background: none;
    border: 1px solid var(--c-ink);
    border-radius: 0;
    padding: 12px 22px;
    color: var(--c-ink);
    transition: background 0.15s ease, color 0.15s ease;
  }
  .ph-book__cta .wp-block-button__link:hover {
    background: var(--c-ink); color: var(--c-paper); text-decoration: none;
  }

  /* --- CV ------------------------------------------------------------------*/
  .ph-cv { padding-bottom: 160px; }
  .ph-cv > .ph-label { padding-bottom: 40px; }
  .ph-cv__portrait {
    max-width: 640px; margin: 0 auto; padding-bottom: 110px; text-align: center;
  }
  .ph-cv__portrait img {
    width: 100%; display: block;
    transform: rotate(180deg);
    transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* The CV sections are emitted as FLAT flex siblings (heading, table, heading,
   * table …). The design wraps each [heading + table] pair in its own div and
   * puts the 60px gap only BETWEEN whole sections. To reproduce that with the
   * flat markup: no flex `gap` (would land between every heading and its own
   * table), and a 60px top margin on every heading except the first — margins
   * don't collapse in a flex column, so it's exactly 60px section-to-section
   * while the 14px heading→rows spacing stays the heading's own padding. */
  .ph-cv__sections { max-width: 940px; display: flex; flex-direction: column; }
  .ph-cv__heading {
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
    color: var(--c-muted); padding-bottom: 14px;
  }
  .ph-cv__heading:not(:first-child) { margin-top: 60px; }
  .ph-cv__row {
    display: flex; gap: 22px; padding: 14px 0;
    border-top: 1px solid var(--c-hairline);
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
  }
  .ph-cv__row .year  { flex: 0 0 64px; color: var(--c-muted); }
  .ph-cv__row .title {
    /* re-assert label type: the `title` token emits a global `.title` utility
     * (:where h1,h2,h3,.title …) that would otherwise blow this up to 18px */
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    letter-spacing: 0.02em;
    flex: 1;
  }
  .ph-cv__row .venue { flex: 0 0 240px; color: var(--c-muted); }

  /* --- CONTACT -------------------------------------------------------------*/
  .ph-contact {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 26px 40px;
    align-items: start;
  }
  .ph-contact__col { max-width: 460px; }
  .ph-contact__label {
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
    color: var(--c-muted); padding-bottom: 20px;
  }
  .ph-contact__list {
    --_lh: var(--list-lh);
    font-size: var(--list-fs);
    font-weight: var(--list-fw);
    line-height: var(--list-lh);
    letter-spacing: var(--list-ls);
    font-family: var(--list-ff);
    text-transform: uppercase; letter-spacing: 0.02em;
  }
  .ph-contact__list .sub { padding-top: 18px; color: var(--c-muted); }
  /* Design: the trailing Instagram/Newsletter line carries the same 18px lead-in
   * as a `.sub` label (padding-top:18px) but keeps the normal ink color. */
  .ph-contact__list .row:last-child { padding-top: 18px; }
  .ph-contact img { width: 100%; display: block; }

  /* --- mobile (INVENTED — no design spec) ----------------------------------*/
  @media (max-width: 48rem) {
    .ph-home__nav { left: var(--ph-pad-x); top: 96px; }
    .ph-plate--pair { flex-direction: column; }
    .ph-statement { flex-direction: column; gap: 20px; margin-top: 60px; }
    .ph-statement__meta { flex: none; }
    .ph-book { grid-template-columns: 1fr; }
    .ph-book + .ph-book { padding-top: 60px; }
    .ph-cv__row { flex-wrap: wrap; gap: 6px 18px; }
    .ph-cv__row .venue { flex-basis: 100%; }
    .ph-contact { grid-template-columns: 1fr; }
  }
}
/* ============================================================================
 * Gutenberg-block markup deltas. The old shortcode markup was bare div/img/p;
 * the editable pages emit WP-core blocks (image/gallery/table/query/button) +
 * gutenx xfield wrappers. These rules neutralize core block defaults (@layer wp)
 * and wire the new markup to the ph-* look above — nothing here restates a rule
 * already declared. Tokens + typo mixin only.
 * ==========================================================================*/
@layer panda {

  /* --- image plates (wp:image / wp:gallery) --------------------------------*/
  /* zero core figure/gallery margins; descendant reach covers the pair images
   * nested one level below .ph-plates inside the gallery figure. */
  .ph-plates > * { margin: 0; }
  .ph-plates figure { margin: 0; }
  .ph-plate--full.wp-block-image img { width: 100%; height: auto; }

  /* pair = wp:gallery(columns 2). The gallery figure is the flex row; each
   * nested .wp-block-image is a flex cell. JS sets flex-grow = aspect ratio on
   * the cell (img.closest('.ph-plate--pair > *')), so keep flex-basis 0 + auto
   * width and let JS drive grow — don't fight it. */
  .ph-plate--pair.wp-block-gallery { display: flex; gap: var(--ph-gap); margin: 0; }
  .ph-plate--pair.wp-block-gallery > .wp-block-image {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
  }

  /* Single-gallery plates: ONE wp:gallery holding every plate (flatter content —
   * one block to manage) that reproduces the mixed full/pair layout. Row gap 60px
   * matches the old .ph-plates column gap; column gap = --ph-gap matches the pair
   * gap. Flex-wrap + full-width 100% rows give clean row breaks: a `.ph-plate--full`
   * takes its own row; the remaining images justify 2-up (JS sets flex-grow =
   * aspect ratio, same as the old pairs). imageCrop is off so images keep aspect. */
  .ph-plates-gallery.wp-block-gallery {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;                 /* undo core gallery's align-items:center */
    gap: 60px var(--ph-gap);
    margin: 0;
  }
  .ph-plates-gallery.wp-block-gallery > .wp-block-image {
    display: block;                          /* undo core has-nested-images flex column */
    flex: 1 1 0;                             /* pair cell — JS sets flex-grow = aspect */
    width: auto;
    min-width: 0;
    margin: 0;
  }
  .ph-plates-gallery.wp-block-gallery > .ph-plate--full {
    flex: 0 0 100%;                          /* full plate — own row */
  }
  .ph-plates-gallery.wp-block-gallery > .wp-block-image img {
    width: 100%;
    height: auto;
    -o-object-fit: initial;
       object-fit: initial;                     /* undo core is-cropped object-fit:cover/fill */
    display: block;
  }
  /* Core gallery overlays nested figcaptions (absolute + gradient); the standalone
   * plates render captions BELOW the image. Restore that so the look is unchanged. */
  .ph-plates-gallery.wp-block-gallery figcaption.wp-element-caption {
    position: static;
    background: none;
    text-shadow: none;                       /* core overlays add a blur shadow for legibility */
    max-width: none;
    padding: 10px 0 0;
  }

  /* captions (figcaption.wp-element-caption) → cap look, scoped to plates,
   * book image, and cv portrait so it can't touch unrelated captions. */
  .ph-plates figcaption,
  .ph-book__img figcaption,
  .ph-cv__portrait figcaption {
    --_lh: var(--cap-lh);
    font-size: var(--cap-fs);
    font-weight: var(--cap-fw);
    line-height: var(--cap-lh);
    letter-spacing: var(--cap-ls);
    font-family: var(--cap-ff);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--c-muted);
    text-align: left;
    margin: 0;
    padding-top: 10px;
  }

  /* --- gutenx xfield sandwich ----------------------------------------------*/
  /* xfield renders <div.xfield-wrapper><TAG.xfield-value>…</TAG></div>; collapse
   * both so the value sits directly in its ph-* flex/flow parent. Scoped. */
  .ph-series-head__right .xfield-wrapper,
  .ph-series-head__right .xfield-value,
  .ph-statement .xfield-wrapper,
  .ph-statement .xfield-value { display: contents; }
  /* post-title (h2) styled as the series-head label, not a heading. */
  .ph-series-head__title { font: inherit; margin: 0; }

  /* --- HOME name + nav (wp:paragraph) --------------------------------------*/
  .ph-home__name, .ph-home__nav p { margin: 0; }

  /* --- CV rows as wp:table (table.ph-cv__rows): 3 cols year/title/venue -----*/
  /* Design CV rows are borderless flex rows with a single hairline border-top
   * (font 12 / #999 year+venue / #333 title). Core `@layer wp` table styles put
   * a 1px border on every td — zero the other three and keep only border-top.
   * Column widths reproduce the design's `flex:0 0 64px` year + 22px gap +
   * flex:1 title + `flex:0 0 240px` venue: under border-box the year cell is
   * 64px content + 22px gap = 86px, so the title text edge lands at 346 (= 260
   * sidebar + 86), the venue at 940-wide `.ph-cv__sections` right edge − 240. */
  .ph-cv__rows { border-collapse: collapse; width: 100%; margin: 0; border: 0; }
  .ph-cv__rows td {
    --_lh: var(--label-lh);
    font-size: var(--label-fs);
    font-weight: var(--label-fw);
    line-height: var(--label-lh);
    letter-spacing: var(--label-ls);
    font-family: var(--label-ff);
    /* Design CV rows use bare `font-size:12px` (line-height:normal); the shared
     * `label` token carries a taller leading for the sidebar/eyebrows. Override
     * line-height HERE ONLY (not the token) so rows are 45px like the design. */
    line-height: normal;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 14px 0;
    border: 0;
    border-top: 1px solid var(--c-hairline);
    vertical-align: baseline;
    color: var(--c-ink-soft);
  }
  .ph-cv__rows td:first-child { width: 86px; padding-right: 22px; color: var(--c-muted); } /* year: 64 + 22 gap */
  .ph-cv__rows td:nth-child(2) { padding-right: 22px; }                                     /* title: gap before venue */
  .ph-cv__rows td:last-child  { width: 240px; color: var(--c-muted); }                      /* venue */

  /* --- BOOKS as wp:query > wp:post-template ---------------------------------*/
  .ph-books .wp-block-post-template {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 100px;
  }
  .ph-books .wp-block-post-template > li { margin: 0; }
  .ph-books .wp-block-post-template > li + li {
    border-top: 1px solid var(--c-hairline);
    padding-top: 100px;
  }

  /* --- CONTACT lists (wp:paragraph) ----------------------------------------*/
  .ph-contact__list p { margin: 0; }

}
/* PDF/print body shell (dormant — _assembled_print is currently empty). Kept
 * as native nesting; postcss-nesting flattens it. Mirrors the old
 * frontend.scss `body.pdf-mode { … }` block. */
body.pdf-mode {

  margin-top: 1px !important;
  padding-top: 0 !important;
}
html:has(body.pdf-mode) {
    margin: 0 !important;
    padding: 0 !important;
  }
body.pdf-mode > :first-child {
    margin-top: 0 !important;
  }

/*# sourceMappingURL=frontend.css.map */
