/* Kelvin Film Lab — visual page builder blocks.
   Loaded by the public site and by the admin's editing canvas, so a block
   looks the same in both. It uses the design tokens kelvin-theme.css already
   defines rather than introducing new colours or type scales; the builder
   offers presets, not free CSS, and this file is where those presets live. */

.pb { position: relative; }
/* The same gutter and maximum width as the site's own .container, taken from
   kelvin-theme.css tokens, so a block lines up with the sections around it.
   The fallbacks are what the admin canvas uses if the site stylesheet is not
   reachable (the Web app not running). */
.pb-inner { width: min(var(--max, 1480px), calc(100% - 2 * var(--pad, clamp(18px, 3.3vw, 52px)))); margin: 0 auto; }

/* ---- content width presets ---- */
.pb-w-narrow  .pb-inner { max-width: 760px; }
.pb-w-normal  .pb-inner { max-width: 1080px; }
.pb-w-wide    .pb-inner { max-width: 1480px; }
.pb-w-full    .pb-inner { width: 100%; max-width: none; }

/* ---- background presets ---- */
.pb-bg-light  { background: var(--bg, #f6f4ef); color: var(--text, #16150f); }
.pb-bg-dark   { background: #0a0a0a; color: #f4f1eb; }
.pb-bg-accent { background: var(--red, #df2525); color: #fff; }
.pb-bg-dark .pb-eyebrow, .pb-bg-accent .pb-eyebrow { color: rgba(255,255,255,.75); }
.pb-bg-dark .pb-body, .pb-bg-accent .pb-body { color: rgba(255,255,255,.86); }

/* ---- spacing presets ----
   Held as custom properties rather than applied directly, so a page can add to
   a block's spacing without overriding the editor's choice — which is how the
   first block on a page reserves room for the fixed site header below. */
.pb { --pb-pt: 0px; --pb-pb: 0px; --pb-offset-top: 0px; }
.pb { padding-top: calc(var(--pb-pt) + var(--pb-offset-top)); padding-bottom: var(--pb-pb); }
.pb-pt-none   { --pb-pt: 0px; }
.pb-pt-small  { --pb-pt: clamp(24px, 4vw, 44px); }
.pb-pt-medium { --pb-pt: clamp(48px, 8vw, 96px); }
.pb-pt-large  { --pb-pt: clamp(80px, 13vw, 168px); }
.pb-pb-none   { --pb-pb: 0px; }
.pb-pb-small  { --pb-pb: clamp(24px, 4vw, 44px); }
.pb-pb-medium { --pb-pb: clamp(48px, 8vw, 96px); }
.pb-pb-large  { --pb-pb: clamp(80px, 13vw, 168px); }

/* The public site's header sits fixed over the page, so whatever block an
   editor puts first has to start below it. The admin canvas has no such header
   and sets no offset, which is why this lives on the page wrapper. */
.pb-page > .pb:first-child { --pb-offset-top: 82px; }

/* ---- alignment ---- */
.pb-align-center .pb-inner { text-align: center; }
.pb-align-center .pb-buttons { justify-content: center; }
.pb-align-center .pb-body { margin-left: auto; margin-right: auto; }

/* ---- typography ---- */
.pb-eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 13px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted, #6f6b62); margin-bottom: 18px;
}
.pb-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--red, #df2525); }
.pb-heading { font-size: clamp(38px, 7vw, 104px); line-height: .95; letter-spacing: -.045em; margin: 0 0 22px; overflow-wrap: break-word; }
.pb-heading-page { font-size: clamp(34px, 5.5vw, 76px); }
.pb-statement .pb-heading { font-size: clamp(32px, 5vw, 68px); line-height: 1.05; letter-spacing: -.03em; }
.pb-richtext .pb-heading, .pb-imagetext .pb-heading { font-size: clamp(26px, 3.2vw, 42px); letter-spacing: -.02em; }
.pb-subheading { font-size: clamp(17px, 2vw, 21px); line-height: 1.5; margin: 0 0 20px; opacity: .88; }
.pb-body { font-size: 17px; line-height: 1.72; max-width: 68ch; }
.pb-body p { margin: 0 0 1em; }
.pb-body p:last-child { margin-bottom: 0; }

/* ---- buttons ---- */
.pb-buttons { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
.pb-btn {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  border: 1px solid currentColor; text-decoration: none; font-weight: 600;
  transition: background .18s ease, color .18s ease;
}
.pb-btn-small  { padding: 9px 18px;  font-size: 15px; min-height: 40px; }
.pb-btn-medium { padding: 13px 26px; font-size: 16px; min-height: 48px; }
.pb-btn-large  { padding: 17px 34px; font-size: 17px; min-height: 56px; }
.pb-btn-rounded { border-radius: 8px; }
.pb-btn-pill    { border-radius: 999px; }
.pb-btn-filled  { background: var(--red, #df2525); border-color: var(--red, #df2525); color: #fff; }
.pb-btn-filled:hover { filter: brightness(1.08); }
.pb-btn-outline { background: transparent; }
.pb-btn-outline:hover { background: currentColor; }
.pb-btn-outline:hover { color: inherit; }
.pb-btn-textlink { background: none; border-color: transparent; padding-left: 0; padding-right: 0; text-decoration: underline; text-underline-offset: 5px; }

/* ---- media ---- */
.pb-media { margin-top: 28px; }
.pb-media-full { margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); width: 100vw; }
.pb-image { display: block; width: 100%; height: auto; border-radius: 10px; }
.pb-media-full .pb-image { border-radius: 0; }
.pb-fit-cover   { object-fit: cover; }
.pb-fit-contain { object-fit: contain; background: rgba(0,0,0,.04); }
.pb-ratio-auto          { aspect-ratio: auto; }
.pb-ratio-square        { aspect-ratio: 1 / 1; }
.pb-ratio-landscape16x9 { aspect-ratio: 16 / 9; }
.pb-ratio-portrait4x5   { aspect-ratio: 4 / 5; }
.pb-ratio-cinema21x9    { aspect-ratio: 21 / 9; }

/* ---- image + text layouts ---- */
.pb-media-text { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 4vw, 64px); align-items: center; }
.pb-media-text .pb-media { margin-top: 0; }
.pb-layout-imagelefttextright .pb-media-text > .pb-media { order: 1; }
.pb-layout-imagelefttextright .pb-media-text > .pb-copy  { order: 2; }
.pb-layout-textleftimageright .pb-media-text > .pb-media { order: 2; }
.pb-layout-textleftimageright .pb-media-text > .pb-copy  { order: 1; }
.pb-layout-stacked .pb-media-text { grid-template-columns: 1fr; }
@media (max-width: 820px) { .pb-media-text { grid-template-columns: 1fr; } }

/* ---- video ---- */
/* The frame a video sits in, not the block.

   This used to be called .pb-video, which is also the class a Video block's
   own <section> gets - every block carries pb-{type}. The 16:9 was therefore
   applied to the whole section as well, which on a block with little text
   forces the entire band to sixteen-by-nine of the full page width and opens
   a hole underneath the video. Renaming the frame is the fix; a block type
   can no longer collide with a component. */
.pb-videoframe { margin-top: 28px; aspect-ratio: 16 / 9; }
.pb-videoframe iframe { width: 100%; height: 100%; border: 0; border-radius: 10px; display: block; }

/* A file hosted here rather than embedded. Without a size it falls back to the
   element default of 300x150 inside a box the block already reserved at 16:9. */
.pb-videoframe video { width: 100%; height: 100%; border-radius: 10px; display: block; object-fit: contain; background: #16150f; }

/* ---- divider ---- */
.pb-divider { border: 0; border-top: 1px solid currentColor; opacity: .18; margin: 0; }

/* ---- feeds ---- */
.pb-feed { margin-top: 34px; display: grid; gap: 20px; }
.pb-feed-grid { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.pb-feed-list { grid-template-columns: 1fr; }
.pb-feed-item { display: block; color: inherit; text-decoration: none; }
.pb-feed-list .pb-feed-item { display: grid; grid-template-columns: 220px 1fr; gap: 22px; align-items: center; }
@media (max-width: 700px) { .pb-feed-list .pb-feed-item { grid-template-columns: 1fr; } }
.pb-feed-media { background: rgba(0,0,0,.06); border-radius: 10px; overflow: hidden; aspect-ratio: 16 / 10; }
.pb-bg-dark .pb-feed-media { background: rgba(255,255,255,.08); }
.pb-feed-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pb-feed-title { font-size: 19px; font-weight: 600; margin: 12px 0 4px; }
.pb-feed-meta { font-size: 13px; letter-spacing: .1em; text-transform: uppercase; opacity: .62; margin: 0 0 6px; }
.pb-feed-summary { font-size: 15px; line-height: 1.6; opacity: .82; margin: 0; }
.pb-feed-empty { margin-top: 26px; padding: 26px; border: 1px dashed currentColor; border-radius: 10px; opacity: .65; }
.pb-feed-empty p { margin: 0; font-size: 15px; }

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

/* ---- the hero block ----
   The prototype's opening frame: a dark, near-full-height panel with the
   headline set on the baseline. The static strip of studio disciplines and the
   short right-hand panel are site chrome rather than editable copy, so the page
   hands them in as a slot; everything else here is the block's own. */
/* ---- hero ----
   The approved prototype's opening block: a dark wash with an angled panel set
   into it, the headline over it, and a narrow column on the right carrying the
   selected-work note and the call to action. */
.pb-hero { min-height: 100svh; display: flex; align-items: flex-end; overflow: hidden; position: relative; }
.pb-hero .pb-heading { font-size: clamp(46px, 9.2vw, 148px); font-weight: 700; letter-spacing: -.07em; line-height: .78; }
.pb-hero .pb-subheading, .pb-hero .pb-body { max-width: 530px; color: #c8c8c8; }

/* The backdrop. Decorative and behind everything, so it never takes a click
   or a tab stop away from the text on top of it. */
.pb-hero-media {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(circle at 73% 34%, rgba(223,37,37,.22), transparent 22%),
    linear-gradient(120deg, rgba(0,0,0,.92) 7%, rgba(0,0,0,.30) 52%, rgba(0,0,0,.80) 100%),
    linear-gradient(155deg, #171717 0%, #262626 35%, #0a0a0a 65%, #1a1a1a 100%);
}

/* The angled panel, and the frame the showreel plays inside. The panel is
   drawn whether or not there is a video, so the page looks like the design
   before anything has been uploaded. */
.pb-hero-media::before {
  content: ""; position: absolute; width: 44vw; height: 58vw; right: 4vw; top: 2vh;
  border: 1px solid rgba(255,255,255,.14); transform: rotate(8deg);
  background: linear-gradient(135deg, #262626, #111 48%, #282828);
  box-shadow: 0 40px 120px #000;
}

/* The video sits in the same angled box, clipped to it. object-fit: cover so a
   clip of any shape fills the panel rather than letterboxing inside it. */
.pb-hero-video {
  position: absolute; width: 44vw; height: 58vw; right: 4vw; top: 2vh;
  transform: rotate(8deg); object-fit: cover; display: block;
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 40px 120px #000;
  /* Dimmed, because the headline sits over it and has to stay readable
     whatever footage an editor uploads. */
  opacity: .55; filter: saturate(.85);
}

.pb-hero-showreel {
  position: absolute; right: clamp(18px, 4vw, 64px); top: 105px;
  font-size: 13px; letter-spacing: .17em; text-transform: uppercase;
  color: #cfcfcf; opacity: .72;
}

/* Everything the block writes goes above the backdrop. */
.pb-hero > .pb-inner { position: relative; z-index: 1; }

/* Two columns, as the design has them: the headline wide on the left, the
   selected-work note narrow on the right, both sitting on the baseline. */
.pb-hero > .pb-inner {
  display: grid; grid-template-columns: 1.45fr .55fr; align-items: end;
  column-gap: 30px; row-gap: 0;
}
.pb-hero > .pb-inner > * { grid-column: 1; }

/* The slot carries the page's own two pieces - the EDIT / COLOR / FINISH strip
   and the aside - so its children have to become grid items themselves rather
   than sit inside a wrapper that is one. */
.pb-hero > .pb-inner > .pb-slot { display: contents; }
.pb-hero .hero-meta { grid-column: 1; }
.pb-hero .hero-right { grid-column: 2; grid-row: 1 / -1; align-self: end; justify-self: end; max-width: 315px; }

.pb-hero .hero-meta {
  display: flex; gap: 30px; margin-top: 28px; flex-wrap: wrap;
  font-size: 13px; letter-spacing: .15em; text-transform: uppercase; color: #9b9b9b;
}
.pb-hero .hero-right .label { font-size: 13px; letter-spacing: .18em; text-transform: uppercase; color: #9a9a9a; }
.pb-hero .hero-right p { font-size: 16px; line-height: 1.5; color: #d1d1d1; margin: 10px 0 20px; }

/* One column on a phone, and the panel moved off to the side as the prototype
   does it, so it stays a backdrop rather than crowding the headline. */
@media (max-width: 900px) {
  .pb-hero > .pb-inner { grid-template-columns: 1fr; row-gap: 40px; }
  .pb-hero > .pb-inner > * { grid-column: 1; }
  .pb-hero .hero-right { grid-column: 1; grid-row: auto; justify-self: start; }
  .pb-hero-media::before,
  .pb-hero-video { width: 76vw; height: 104vw; right: -19vw; top: 16vh; }
  .pb-hero-showreel { top: 87px; }
  .pb-hero .hero-meta { gap: 14px; }
}

/* A looping video in the corner of the eye is exactly what this setting is
   for. Hiding it uncovers the angled gradient panel underneath, which is the
   design's own default - so the hero still looks finished, it just stops
   moving. The script pauses it as well, so nothing decodes out of sight. */
@media (prefers-reduced-motion: reduce) {
  .pb-hero-video { display: none; }
}

/* The dark page header of an inner page, as .page-hero always looked. */
.pb-pageheader.pb-bg-dark .pb-body,
.pb-pageheader.pb-bg-dark .pb-subheading { color: #c8c8c8; max-width: 620px; }

/* ---- slots ----
   A block whose records the page lays out itself. The slot keeps the site's own
   markup and classes, so the portfolio grid, the numbered services list and the
   inquiry form look exactly as they always did. */
.pb-slot { margin-top: 34px; }
