/* ============================================================================
   site.css — jessicaresler.com composition layer.

   The ONLY legal contents of this file are: (a) positioning/sizing of the
   site's own images and video, (b) two animations the kit does not ship.
   It declares no color, no font-family, no shadow, no radius of its own —
   every value below is a token read from themes/signal.css.

   If you need something here that isn't image geometry, it belongs in the
   kit instead: add it to themes/signal.css, re-approve, then use it.
   ========================================================================== */

/* --- [hidden] must actually hide ----------------------------------------
   The browser's built-in `[hidden] { display: none }` is a low-specificity
   UA rule, so any kit class that sets `display` beats it — `.cta` and
   `.stack` are both `display: grid`. Without this, `hidden` silently does
   nothing on them and the contact form's confirmation renders *below* the
   form instead of replacing it. base.css doesn't normalise this. */
[hidden] { display: none !important; }

/* Focus moves to the contact confirmation so keyboard users land on it and
   the next Tab starts from a sensible place. It is a non-interactive status
   container, and `role="status" aria-live="polite"` already announces it, so
   the focus ring is suppressed on this one element only. */
#formThanks:focus,
#formThanks:focus-visible { outline: none; }

/* --- mast: the kit styles it, the site pins it ------------------------- */
.mast { position: sticky; top: 0; z-index: 50; }

/* --- the chain mark ---------------------------------------------------- */
/* chains.png is a 1280x720 frame with the medallion sitting as a centred
   ~622x601 square — i.e. half the frame is empty side padding. Forcing it
   into a square box warped it; `contain` would shrink it to the 16:9 width.
   `cover` on a square box crops the dead sides and lets the medallion fill
   the mark properly. */
.mast__mark img {
  width: 48px;
  height: 48px;
  object-fit: cover;
  animation: mark-spin 18s linear infinite;
}
@keyframes mark-spin { to { transform: rotate(360deg); } }

/* --- hero: one media band, full width, holding the film ---------------- */
.hero__band > .hero__film {
  flex: 1 0 100%;
  height: clamp(260px, 52vh, 560px);
  overflow: hidden;
  /* fill, radius and drop-shadow all inherit from the kit's `.hero__band > *` */
}
.hero__band > .hero__film video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* crop from the bottom, not the middle — keeps the face in frame */
  object-position: 50% 12%;
}

/* --- portfolio: real logo artwork inside the kit's logowall ------------ */
/* DEVIATION FROM KIT (deliberate, documented): the kit sets
   `.logowall { opacity: .6 }`, which is correct for the uniform text
   wordmarks the kit ships. These are real brand logos in mixed tones, and
   at 60% they wash out unevenly against the signal canvas. Full strength
   here; the fade moves to hover instead. If the kit ever gains a
   `.logowall--art` variant, delete this and use that. */
[data-theme="signal"] .logowall { opacity: 1; }
/* Two tiers. CAPE and Locally Yours are the operating businesses and lead at
   roughly 2.4x the cap height of the rest, which sit below as a lighter
   secondary row. Each tier is normalised on CAP HEIGHT, not width — the marks
   have very different aspect ratios (BLEXX 4.24:1, Locally Yours 2.10:1), so
   matching widths would make them wildly different sizes.

   Dirty Hands has no wordmark artwork; it is a typeset mark set in Anton,
   which this site already loads. It sets as live type through the kit's
   `.logowall span`, sized capHeight / 0.872 (Anton's measured cap ratio)
   so it lands on the same baseline as the images. */

[data-theme="signal"] .logowall--lead img   { height: clamp(52px, 5.6vw, 84px); }
[data-theme="signal"] .logowall--lead span  { font-size: clamp(60px, 6.4vw, 96px); }
[data-theme="signal"] .logowall--lead       { gap: clamp(3rem, 8vw, 7rem); }

[data-theme="signal"] .logowall--rest img   { height: clamp(22px, 2.3vw, 30px); }
[data-theme="signal"] .logowall--rest span  { font-size: clamp(25px, 2.64vw, 34px); }
[data-theme="signal"] .logowall--rest       { gap: clamp(2rem, 5vw, 4rem); opacity: 0.82; }

[data-theme="signal"] .logowall img  { width: auto; max-width: 300px; object-fit: contain; }
[data-theme="signal"] .logowall span { line-height: 1; letter-spacing: -0.005em; }

.logowall a { transition: opacity var(--dur) var(--ease); }
.logowall a:hover { opacity: 0.6; }

/* --- marquee: the kit ships the type, the site ships the travel -------- */
/* .marquee is overflow:hidden + nowrap already; this adds the loop. The
   track is duplicated in markup so translateX(-50%) is seamless. */
.marquee__track {
  display: flex;
  gap: var(--s-5);
  align-items: center;
  flex: 0 0 auto;
  animation: marquee-travel 32s linear infinite;
}
@keyframes marquee-travel { to { transform: translateX(-50%); } }

/* --- footer ------------------------------------------------------------
   The cutout is a signature, not a hero — it sits beside the link columns
   rather than dominating them. Footer copy moves up to the reading tier;
   the kit's footer sizes assume app chrome. */
.foot__cutout { width: clamp(84px, 8.5vw, 118px); height: auto; }
[data-theme="signal"] .foot__c a     { font-size: var(--fs-body); }
[data-theme="signal"] .foot .small   { font-size: var(--fs-body); }
[data-theme="signal"] footer .micro  { font-size: var(--fs-sm); }

/* --- work cards: let the capability copy breathe ----------------------- */
.step p { color: var(--t-mid); }

@media (prefers-reduced-motion: reduce) {
  .mast__mark img,
  .marquee__track { animation: none; }
}

/* --- mast at small widths ----------------------------------------------
   The kit's mast assumes a short mark ("SIGNAL"). "Jessica Resler" is two
   words and wraps under ~560px. Keep the name on one line and drop the
   secondary nav item — Press is still one tap away in the footer, and it
   leaves a single unambiguous mobile action. */
.mast__mark { white-space: nowrap; }
@media (max-width: 560px) {
  .mast__nav .btn--ghost { display: none; }
}

/* The editorial reading scale now lives in the kit itself, opted into with
   data-scale="editorial" on <html>. Nothing to override here. */

/* --- bio aside ----------------------------------------------------------
   The stats/credentials column is far shorter than the prose beside it.
   Grid's default `align-content: stretch` was inflating its rows — and the
   stat tiles with them — to fill the leftover height. Hold natural size. */
.bio-aside,
.bio-aside .grid-2 { align-content: start; }

/* base.css resets hr's border but not its margin, so the kit's `.u-rule`
   divider carries the UA default ~8.5px above and below. Zero it so the
   rule sits on the list's own rhythm. */
[data-theme="signal"] .u-rule { margin: 0; }

/* --- stat tile density --------------------------------------------------
   The kit's `.tile` is `align-content: space-between` at `min-height: 190px`,
   which is right on a dashboard where the number should float clear of its
   label. Used inline beside body copy, that reads as a gap rather than as
   breathing room. Number and label are pulled together here.
   → Candidate for a `.tile--compact` variant in the kit. */
[data-theme="signal"] .tile {
  align-content: start;
  gap: var(--s-2);
  min-height: 0;
}

/* --- brand tile ---------------------------------------------------------
   Interests grid: the kit's stat tile carries a display-scale number; a
   brand name at that size shouts. Held to a word-scale weight so a row of
   four reads as a list, with the relationship as the quiet second line.
   → Candidate for a `.tile--brand` variant in the kit. */
[data-theme="signal"] .tile--brand { gap: var(--s-1); padding: var(--s-4) var(--s-5); }
[data-theme="signal"] .tile--brand .tile__n {
  font-size: clamp(1.25rem, 1.6vw, 1.5rem);
  letter-spacing: -0.02em;
  font-variant-numeric: normal;
}
/* linked brand tiles: quiet like the logowall, no link chrome */
a.tile--brand { text-decoration: none; transition: opacity var(--dur) var(--ease); }
a.tile--brand:hover { opacity: 0.6; }

/* download tiles: the artwork is the tile — square preview, label under */
[data-theme="signal"] a.tile--dl {
  gap: var(--s-3);
  padding: var(--s-4);
  text-decoration: none;
  transition: opacity var(--dur) var(--ease);
}
[data-theme="signal"] a.tile--dl:hover { opacity: 0.75; }
[data-theme="signal"] .tile--dl img { width: 100%; aspect-ratio: 1; object-fit: contain; }

/* --- thought-leadership entries -----------------------------------------
   AKQA-style editorial grid: category eyebrow over a headline, no card
   chrome — a hairline above each entry carries the structure, the type
   does the rest. Two-up on desktop, stacks on mobile. */
[data-theme="signal"] .posts {
  display: grid;
  gap: var(--s-7) var(--s-6);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
}
[data-theme="signal"] .post {
  display: grid;
  align-content: start;
  gap: var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  text-decoration: none;
}
[data-theme="signal"] .post .h2 { transition: color var(--dur) var(--ease); }
[data-theme="signal"] a.post:hover .h2 { color: var(--signal-deep); }

/* entry photo: image-led like the AKQA reference — sits above the eyebrow,
   cropped to a steady ratio so mixed source photos rack up evenly */
[data-theme="signal"] .post__img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--r-xl);
  margin-bottom: var(--s-2);
  transition: opacity var(--dur) var(--ease);
}
[data-theme="signal"] a.post:hover .post__img { opacity: 0.85; }

/* --- stance article ------------------------------------------------------
   Long-form piece: one measured prose column, figures break the measure. */
[data-theme="signal"] .article { max-width: 68ch; }
[data-theme="signal"] .article__fig { display: grid; gap: var(--s-2); margin-block: var(--s-4); }
[data-theme="signal"] .article__fig img { width: 100%; height: auto; border-radius: var(--r-xl); }
[data-theme="signal"] .article__hero {
  width: 100%;
  aspect-ratio: 5 / 2;
  object-fit: cover;
  border-radius: var(--r-xl);
}

/* --- scroll reveal -------------------------------------------------------
   Text and cards slide up as they enter the viewport. The hidden state is
   ONLY applied by script.js adding .reveal, so nothing disappears without
   JavaScript; reduced-motion users get everything static. */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* --- footer film ---------------------------------------------------------
   The video IS the footer: it fills the whole ink surface as a backdrop,
   under a scrim that keeps the links readable, and the footer content
   floats on top. */
[data-theme="signal"] footer[data-surface="ink"] { position: relative; overflow: hidden; }
[data-theme="signal"] .foot-hero { position: absolute; inset: 0; z-index: 0; }
[data-theme="signal"] .foot-hero video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
[data-theme="signal"] .foot-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(5, 5, 8, 0.55);
}
[data-theme="signal"] footer[data-surface="ink"] > .wrap { position: relative; z-index: 1; }

/* --- stances signup ------------------------------------------------------
   Slim capture row under the entries. Same hairline language as the posts;
   the field and button sit on one line and wrap on mobile. */
[data-theme="signal"] .signup {
  display: grid;
  gap: var(--s-4);
  margin-top: var(--s-8);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}
[data-theme="signal"] .signup__form {
  display: flex;
  align-items: flex-end;
  gap: var(--s-3);
  flex-wrap: wrap;
  max-width: 560px;
}
[data-theme="signal"] .signup__form .field { flex: 1 1 260px; }
