/* =============================================================================
   CHOPAKA LABS — PHOTOGRAPHY / IMAGERY TREATMENT
   -----------------------------------------------------------------------------
   Reusable image-treatment utilities built on the brand tokens in tokens.css.
   Load AFTER tokens.css.

   TWO TIERS (this is the whole system):
     TIER A — THE HONEST GRADE  (.ph-grade)
       The everyday treatment: editorial, in-app, documentary. Real color,
       neutral white balance, just disciplined — a touch less saturation, a
       touch more contrast. Let the light tell the truth. Use this for ~90% of
       imagery.
     TIER B — THE DUOTONE  (.ph-duotone)
       The brand-locked, stylized treatment: slate shadows → steel highlights.
       Reserved for HERO / MARKETING / COVER moments — never the everyday photo.
       It is loud on purpose; using it everywhere kills it.

   COMPOSE with a wrapper:
       <div class="ph-frame ph-landscape ph-vignette ph-grain">
         <img class="ph-grade" src="orchard.jpg" alt="" />
       </div>
   or, for a fillable slot (persists the drop):
       <div class="ph-frame ph-duotone ph-wide">
         <image-slot id="hero" placeholder="Drop a wide land shot"></image-slot>
       </div>

   PRINCIPLE: the land is the hero, the grade is invisible, the duotone is rare.
   ============================================================================= */

/* ---- The frame: every treated image lives in one ----------------------- */
/* position + isolation so overlay pseudos blend ONLY with the image inside,
   not the page behind it. overflow clips the duotone bleed and reframe spill. */
.ph-frame {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--color-bg-deep);   /* shows while a slot is empty */
}
.ph-frame > img,
.ph-frame > image-slot,
.ph-frame > picture > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Aspect-ratio helpers (optional; or size the frame yourself) -------- */
.ph-wide      { aspect-ratio: 21 / 9; }   /* hero banners, the wide land shot */
.ph-cinema    { aspect-ratio: 2 / 1;  }   /* section headers */
.ph-landscape { aspect-ratio: 3 / 2;  }   /* default editorial */
.ph-square    { aspect-ratio: 1 / 1;  }   /* grid tiles, social */
.ph-portrait  { aspect-ratio: 4 / 5;  }   /* people, hands, vertical hardware */

/* =============================================================================
   TIER A — THE HONEST GRADE
   Filter-only, so it works on a bare <img> with no wrapper if you like.
   Neutral white balance — we do NOT push a color cast by default.
   ============================================================================= */
.ph-grade {
  filter: saturate(0.90) contrast(1.05) brightness(1.005);
}
/* Opt-in colder variant — a faint frost-night discipline. Use sparingly, e.g.
   dawn / cold-light scenes. Needs the .ph-frame wrapper (uses an overlay). */
.ph-frame.ph-frost::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: var(--steel);
  mix-blend-mode: soft-light;
  opacity: 0.18;
}

/* ---- Atmosphere overlays (Tier A) -------------------------------------- */
/* Grain — the same grayscale fractal noise as the brand background, so photos
   sit in the same air as the UI. Lives on ::before so it can stack with the
   vignette on ::after. */
.ph-frame.ph-grain::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px;
  mix-blend-mode: soft-light;
  opacity: 0.10;
}
/* Vignette — a soft slate fall-off at the edges; keeps text legible over a
   photo and pulls the eye to the subject. */
.ph-frame.ph-vignette::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(120% 120% at 50% 42%,
              transparent 52%,
              color-mix(in srgb, var(--slate-900) 55%, transparent) 100%);
}
/* Scrim — a bottom-up slate gradient for laying type/wordmark over a photo. */
.ph-frame.ph-scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to top,
              color-mix(in srgb, var(--slate-900) 88%, transparent) 0%,
              color-mix(in srgb, var(--slate-900) 30%, transparent) 38%,
              transparent 68%);
}

/* =============================================================================
   TIER B — THE DUOTONE  (hero / marketing only)
   Grayscale the image, then map shadows → slate and highlights → pale steel
   with two blend overlays. Endpoints are CSS vars so a hero can be re-keyed.
     ::before  lighten  → lifts the darkest pixels UP to the shadow color
     ::after   darken   → caps the brightest pixels DOWN to the highlight color
   ============================================================================= */
.ph-frame.ph-duotone {
  --duo-shadow: var(--slate-900);   /* deepest tone */
  --duo-high:   #c9d6e6;            /* pale steel — the cool highlight */
}
.ph-frame.ph-duotone > img,
.ph-frame.ph-duotone > image-slot,
.ph-frame.ph-duotone > picture > img {
  filter: grayscale(1) contrast(1.12) brightness(1.02);
}
.ph-frame.ph-duotone::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--duo-shadow);
  mix-blend-mode: lighten;
}
.ph-frame.ph-duotone::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--duo-high);
  mix-blend-mode: darken;
}
/* Deeper, more saturated hero key — slate → sky. Use when the duotone IS the
   composition (full-bleed cover with the wordmark over it). */
.ph-frame.ph-duotone.ph-duotone--deep { --duo-high: var(--sky); }
/* Most neutral key — slate → cloud. When the blue would fight nearby steel UI. */
.ph-frame.ph-duotone.ph-duotone--ink  { --duo-high: var(--cloud); }

/* =============================================================================
   SVG COLOR-MATRIX DUOTONE  (the robust path — works on <img> AND <image-slot>)
   -----------------------------------------------------------------------------
   The blend-overlay `.ph-duotone` above composes beautifully over a flat <img>,
   but `mix-blend-mode` does NOT compose over a shadow-DOM custom element
   (e.g. the fillable <image-slot>) — you get a washed-out result. These classes
   apply the duotone as an SVG filter ON the element, which DOES pierce shadow
   DOM. Prefer these whenever the target might be an <image-slot>.

   BRAND-LOCKED KEY: **Steel** (`.ph-fx-steel`, slate → pale steel) — restrained,
   sits quietly behind type. `.ph-fx-deep` (slate → sky) is the optional dramatic
   alternate for full-bleed covers where the duotone IS the composition.

   Requires the matching <filter> defs somewhere in the page (a hidden <svg>):

     <svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs>
       <filter id="chopaka-duo-deep" color-interpolation-filters="sRGB">
         <feColorMatrix type="matrix"
           values="0.2126 0.7152 0.0722 0 0  0.2126 0.7152 0.0722 0 0
                   0.2126 0.7152 0.0722 0 0  0 0 0 1 0"/>
         <feComponentTransfer>
           <feFuncR type="table" tableValues="0.141 0.435"/>   <!-- slate900 → sky -->
           <feFuncG type="table" tableValues="0.145 0.620"/>
           <feFuncB type="table" tableValues="0.173 0.765"/>
         </feComponentTransfer>
       </filter>
       <filter id="chopaka-duo-steel" color-interpolation-filters="sRGB"> … 0.788/0.839/0.902 … </filter>
     </defs></svg>
   ============================================================================= */
.ph-fx-deep  { filter: url(#chopaka-duo-deep)  contrast(1.04) brightness(1.02); }
.ph-fx-steel { filter: url(#chopaka-duo-steel) contrast(1.04) brightness(1.02); }

/* =============================================================================
   Caption / credit — mono, like every other piece of metadata in the system.
   ============================================================================= */
.ph-caption {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  color: var(--color-text-subtle);
  margin-top: 10px;
}

/* ---- Reduced transparency / forced colors: keep photos legible --------- */
@media (prefers-reduced-transparency: reduce) {
  .ph-frame.ph-frost::after,
  .ph-frame.ph-grain::before { opacity: 0; }
}

/* Production placeholder for unfilled <image-slot>s (SP2). */
.photo-slot {
  display: grid; place-items: center; width: 100%; aspect-ratio: 4 / 3;
  background: var(--color-surface); border: 1px dashed var(--color-border);
  color: var(--color-text-subtle); overflow: hidden;
}
.photo-slot--rounded { border-radius: 16px; }
.photo-slot--rect { border-radius: 0; }
.photo-slot--circle { border-radius: 50%; aspect-ratio: 1 / 1; }
.photo-slot--pill { border-radius: 999px; }
.photo-slot__hint { font-size: 0.8rem; padding: 0 1rem; text-align: center; opacity: 0.7; }
.photo { display: block; width: 100%; height: auto; object-fit: cover; }
.photo--rounded { border-radius: 16px; }
.photo--circle { border-radius: 50%; aspect-ratio: 1 / 1; object-fit: cover; }
.photo--pill { border-radius: 999px; }
