/* ==========================================================================
   Ege Barış Öncü · portfolio
   --------------------------------------------------------------------------
   EDIT THE PALETTE AND SCALE IN THE FIRST TWO BLOCKS ONLY.
   Everything below reads from these variables. You should never need to
   hunt for a hex code further down the file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. PALETTE: DARK (the default, and what the site is designed for)
   -------------------------------------------------------------------------- */
:root {
  --bg:            #0E0F10;  /* page ground */
  --surface:       #16181A;  /* cards, raised blocks */
  --surface-2:     #1E2124;  /* metadata blocks, tags */
  --border:        #26292C;  /* hairlines */
  --border-strong: #3A3E42;  /* placeholder outlines */

  --text:          #E9E6E2;  /* body */
  --text-strong:   #FFFFFF;  /* headings, bolded keywords */
  --text-muted:    #9B968F;  /* metadata, captions */

  --accent:        #FF6B1F;  /* safety orange: dive gear, not sea blue */
  --accent-soft:   #FF8B4F;  /* hover */
  --accent-ink:    #0E0F10;  /* text sitting ON the accent */

  /* Serif needs more weight and more air on a dark ground than a light one. */
  --prose-weight:  400;
  --prose-leading: 1.75;
}

/* --------------------------------------------------------------------------
   2. PALETTE: LIGHT (the variant; set by the toggle, never automatic)
   -------------------------------------------------------------------------- */
:root[data-theme="light"] {
  --bg:            #F7F5F2;
  --surface:       #FFFFFF;
  --surface-2:     #F0EDE8;
  --border:        #E2DED8;
  --border-strong: #C6C0B6;

  --text:          #1B1D1F;
  --text-strong:   #000000;
  --text-muted:    #5F5C56;

  --accent:        #C2410C;  /* darkened so it still clears contrast on paper */
  --accent-soft:   #9A3412;
  --accent-ink:    #FFFFFF;

  --prose-weight:  400;
  --prose-leading: 1.7;
}

/* --------------------------------------------------------------------------
   3. SCALE AND RHYTHM
   -------------------------------------------------------------------------- */
:root {
  --font-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  --font-prose:   "Source Serif 4", Georgia, "Times New Roman", serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

  /* Prose line length. Deliberately NOT raised much, because 62ch of a proportional
     serif is already ~70 characters a line, the top of the readable range.
     Widening this is the one change that would trade readability for width,
     and readability is the stated first priority. */
  --measure: 64ch;

  /* Content container. Sized for laptops rather than for a 2015 blog: at
     1920 this leaves ~300px of margin a side instead of ~410px. */
  --page-max: 82rem;
  --gutter: clamp(1.25rem, 5vw, 3.5rem);

  --space-section: clamp(4.5rem, 10vw, 8rem);
  --space-block:   clamp(2rem, 4vw, 3rem);

  --radius: 3px;            /* clean and precise, not rounded and friendly */
}

/* --------------------------------------------------------------------------
   4. FONTS: self-hosted, no third-party requests
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Space Grotesk";
  src: url("../fonts/space-grotesk-latin.woff2") format("woff2");
  font-weight: 300 700; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk";
  src: url("../fonts/space-grotesk-latinext.woff2") format("woff2");
  font-weight: 300 700; font-style: normal; font-display: swap;
  /* Carries ş ğ İ. Without this the name renders wrong. */
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("../fonts/source-serif-4-latin.woff2") format("woff2");
  font-weight: 200 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("../fonts/source-serif-4-latinext.woff2") format("woff2");
  font-weight: 200 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2");
  font-weight: 100 800; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono-latinext.woff2") format("woff2");
  font-weight: 100 800; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   5. RESET AND BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;   /* so anchors clear the sticky nav */
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-prose);
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  font-weight: var(--prose-weight);
  line-height: var(--prose-leading);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, picture, svg { display: block; max-width: 100%; height: auto; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
a:hover { color: var(--accent-soft); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius);
}

strong, b { color: var(--text-strong); font-weight: 600; }

::selection { background: var(--accent); color: var(--accent-ink); }

/* Pixel diver cursor. Desktop only, because a custom cursor on touch is pointless,
   and on a trackpad it costs precision. The declaration is inert until the
   PNG exists; browsers silently fall back to the default. Drop the file at
   Assets/cursor-diver.png (32x32, hotspot roughly centre) to switch it on. */
@media (pointer: fine) {
  body { cursor: url("../Assets/cursor-diver.png") 8 8, auto; }
  a, button, summary { cursor: url("../Assets/cursor-diver-pointer.png") 8 8, pointer; }
}

.skip-link {
  position: absolute; left: -9999px;
  background: var(--accent); color: var(--accent-ink);
  padding: 0.75rem 1.25rem; z-index: 100;
  font-family: var(--font-mono); font-size: 0.8rem;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* --------------------------------------------------------------------------
   6. LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--space-section); }
.section + .section { padding-top: 0; }

.prose { max-width: var(--measure); }

/* Head in a left rail, content in the right column. Puts prose on the same
   13rem rail the experience and tools rows already use, so body text across
   the whole page starts at one x position instead of three. Collapses to a
   single column before the rail would squeeze the measure. */
.section-split {
  display: grid;
  grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
  gap: 0.5rem clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
.section-split > .section-head { margin-bottom: 0; }
@media (max-width: 900px) {
  .section-split { grid-template-columns: 1fr; }
  .section-split > .section-head { margin-bottom: var(--space-block); }
}
.prose p + p { margin-top: 1.15em; }
.prose h3 {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 0.98rem + 0.35vw, 1.25rem);
  font-weight: 500;
  line-height: 1.3;
  color: var(--text-strong);
  margin-top: 2.5em;
  margin-bottom: 0.6em;
}
.prose h3:first-child { margin-top: 0; }

/* --------------------------------------------------------------------------
   7. TYPE ROLES
   -------------------------------------------------------------------------- */
.label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.section-head {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 1.2rem + 1vw, 2rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--text-strong);
  margin-bottom: var(--space-block);
}

/* --------------------------------------------------------------------------
   8. SITE NAV
   -------------------------------------------------------------------------- */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.nav__inner {
  display: flex; align-items: center; gap: 1.5rem;
  min-height: 3.5rem;
}
.nav__mark {
  font-family: var(--font-display);
  font-weight: 700; font-size: 0.95rem;
  color: var(--text-strong); text-decoration: none;
  letter-spacing: -0.01em;
  margin-right: auto;
}
.nav__links { display: flex; gap: 1.5rem; list-style: none; padding: 0; }
.nav__links a {
  font-family: var(--font-mono);
  font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted); text-decoration: none;
}
.nav__links a:hover { color: var(--accent); }

.theme-toggle {
  background: none; border: 1px solid var(--border);
  color: var(--text-muted);
  font-family: var(--font-mono); font-size: 0.7rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0.35rem 0.6rem; border-radius: var(--radius);
  cursor: pointer; line-height: 1;
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }

@media (max-width: 640px) {
  .nav__links { gap: 1rem; }
  .nav__links a { font-size: 0.68rem; letter-spacing: 0.04em; }
  .nav__mark { font-size: 0.85rem; }
}
/* Tighten rather than hide. Dropping nav items on a phone costs the reader
   the route to Work, which is the whole point of the page. All four fit at
   360px once the tracking comes off. */
@media (max-width: 460px) {
  .nav__inner { gap: 0.7rem; }
  .nav__links { gap: 0.6rem; }
  .nav__links a { font-size: 0.6rem; letter-spacing: 0.01em; }
  .theme-toggle { font-size: 0.6rem; padding: 0.3rem 0.4rem; }
  .nav__mark { font-size: 0.8rem; }
}

/* --------------------------------------------------------------------------
   9. DEPTH GAUGE: scroll progress rendered as depth.
   Present from first paint at 0 m, per the brief's replacement for a
   generic scroll cue. Chrome layer only; never sits behind body text.
   -------------------------------------------------------------------------- */
.gauge {
  position: fixed;
  right: clamp(0.75rem, 2vw, 1.75rem);
  top: 50%; transform: translateY(-50%);
  z-index: 40;
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  pointer-events: none;
}
.gauge__track {
  width: 2px; height: clamp(120px, 22vh, 200px);
  background: var(--border);
  position: relative; overflow: hidden;
}
.gauge__fill {
  position: absolute; inset: 0 0 auto 0;
  height: var(--p, 0%);          /* --p is set by js/site.js */
  background: var(--accent);
}
.gauge__readout {
  font-family: var(--font-mono);
  font-size: 0.65rem; letter-spacing: 0.1em;
  color: var(--text-muted);
  writing-mode: vertical-rl;
  font-variant-numeric: tabular-nums;
}
.gauge__readout b { color: var(--accent); font-weight: 500; }

/* On narrow screens the vertical gauge would crowd the text column, so it
   becomes a hairline under the nav with the readout inline. */
@media (max-width: 860px) {
  .gauge {
    top: 3.5rem; right: 0; left: 0;
    transform: none;
    flex-direction: row; align-items: center; gap: 0;
  }
  .gauge__track { width: 100%; height: 2px; }
  .gauge__fill { inset: 0 auto 0 0; height: 100%; width: var(--p, 0%); }
  .gauge__readout {
    writing-mode: horizontal-tb;
    position: absolute; right: var(--gutter); top: 0.5rem;
    font-size: 0.6rem;
  }
}

/* --------------------------------------------------------------------------
   10. HERO
   -------------------------------------------------------------------------- */
.hero {
  padding-top: clamp(4rem, 12vh, 8rem);
  padding-bottom: clamp(3.5rem, 9vh, 6rem);
  min-height: min(78vh, 640px);
  display: flex; flex-direction: column; justify-content: center;
}
.hero__name {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 1.6rem + 5.2vw, 5rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--text-strong);
}
.hero__role {
  font-family: var(--font-mono);
  font-size: clamp(0.75rem, 0.7rem + 0.2vw, 0.85rem);
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
  margin-top: 1.25rem;
}
.hero__claim {
  font-size: clamp(1.1rem, 1rem + 0.7vw, 1.5rem);
  line-height: 1.5;
  max-width: 34ch;
  margin-top: clamp(1.75rem, 4vh, 2.75rem);
  color: var(--text);
}

/* --------------------------------------------------------------------------
   11. PROJECT ENTRIES
   -------------------------------------------------------------------------- */

/* Role and ownership always sit ABOVE the game description. The markup
   order enforces it; this only styles it. */
.role-block { margin-bottom: 1.25rem; }
/* The mono type in the cards, the banner and the case study headers sits a
   step above where it started. At 0.65-0.72rem it read as decoration and was
   reported as hard to read; readability is the stated first priority, so it
   wins over the tighter look. Do not shrink these back. */
.role-block dt {
  font-family: var(--font-mono);
  font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-muted);
}
.role-block dd {
  margin: 0.15rem 0 0.75rem;
  font-size: 1.05rem; line-height: 1.45;
  color: var(--text-strong);
  font-weight: 600;
}

.meta {
  font-family: var(--font-mono);
  font-size: 0.82rem; line-height: 1.85;
  color: var(--text-muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.1rem 1.25rem;
}
.meta dt { color: var(--text-muted); opacity: 0.75; }
.meta dd { margin: 0; color: var(--text); }

.tags { display: flex; flex-wrap: wrap; gap: 0.4rem; list-style: none; padding: 0; }
.tags li {
  font-family: var(--font-mono);
  font-size: 0.8rem; line-height: 1.4;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.3rem 0.55rem;
}
.tags li::before { content: "▸ "; color: var(--accent); }

.engine-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.76rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 0.25rem 0.5rem;
}

.pitch {
  font-size: 1.05rem; line-height: 1.6;
  color: var(--text-muted);
  max-width: 58ch;
}

/* FATE: the banner entry */
.banner-project { margin-bottom: var(--space-section); }

/* Full-bleed. The media element sits OUTSIDE .wrap in the markup rather than
   using the usual `width:100vw; margin-left:calc(50% - 50vw)` trick, because 100vw
   includes the scrollbar, so on Windows that trick overflows the page by
   ~15px and needs overflow:hidden to paper over it. Structure is cheaper
   than a hack. */
.banner-project__media {
  width: 100%;
  margin-bottom: var(--space-block);
}
.banner-project__media img,
.banner-project__media .ph--banner {
  width: 100%;
  height: clamp(20rem, 42vw, 44rem);
  aspect-ratio: auto;
  object-fit: cover;
  border-left: 0;
  border-right: 0;
  border-radius: 0;
}
/* Mobile gets the art-directed crop: a taller frame, not a squashed wide one. */
@media (max-width: 719px) {
  .banner-project__media img,
  .banner-project__media .ph--banner {
    height: clamp(22rem, 78vw, 30rem);
    aspect-ratio: auto;
  }
}
.banner-project__body { display: grid; gap: 1.25rem; max-width: 62ch; }
.banner-project__title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.4rem + 1.8vw, 2.75rem);
  font-weight: 700; letter-spacing: -0.02em; line-height: 1;
  color: var(--text-strong);
}
.banner-project__title a { color: inherit; text-decoration: none; }
.banner-project__title a:hover { color: var(--accent); }

/* Arena + Somnium: the card pair */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
}
.card {
  /* Height of the title band. Every card reserves it, so the titles line up
     across the grid whether or not the card carries an award mark. The mark is
     sized from the same value, which is why it is a variable and not a literal
     repeated in two rules. */
  --card-head-h: clamp(3.5rem, 6vw, 5rem);

  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 3vw, 1.75rem);
  display: flex; flex-direction: column; gap: 1rem;
}
.card__title {
  font-family: var(--font-display);
  font-size: 1.5rem; font-weight: 700; letter-spacing: -0.015em; line-height: 1.1;
  color: var(--text-strong);
}
.card__title a { color: inherit; text-decoration: none; }
.card__title a:hover { color: var(--accent); }
.card .pitch { font-size: 1.02rem; }

.more-link {
  font-family: var(--font-mono);
  font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase;
  text-decoration: none;
  align-self: start; margin-top: auto;
}
.more-link::after { content: " →"; }

/* Whole-block click target for the three projects. The title stays the only
   real link, with a transparent pseudo-element stretching it over the block,
   so the markup keeps one destination per project and the tab order does not
   grow. Wrapping each article in an <a> would have nested the headings and
   the meta lists inside a link instead.

   The FATE banner image is deliberately OUTSIDE the target. It is full-bleed
   and about a third of the screen on a phone, and a link stretched over it
   turns an ordinary scroll drag into a navigation. The positioning context is
   .cs-split, the text block under the image, rather than the whole article.
   Do not move this back onto .banner-project.

   Tradeoff: the overlay swallows text selection over the block. Accepted,
   since these are navigation blocks, not prose. */
.banner-project .cs-split,
.card { position: relative; }

.banner-project__title a::after,
.card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* "Read the case study" sits above the overlay so it keeps its own hover
   state. It points at the same page, so nothing breaks if a click lands on
   the overlay instead. */
.banner-project .more-link,
.card .more-link { position: relative; z-index: 2; }

/* The block answers on hover, not just the title. The banner image sits
   outside the target, so hovering it does not signal a link that is not
   there. */
.banner-project .cs-split:hover .banner-project__title a,
.card:hover .card__title a { color: var(--accent); }

/* --------------------------------------------------------------------------
   12. PLACEHOLDERS: deliberately ugly so they cannot ship by accident
   -------------------------------------------------------------------------- */
.ph {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.4rem;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: repeating-linear-gradient(
    45deg,
    transparent, transparent 9px,
    color-mix(in srgb, var(--border) 45%, transparent) 9px,
    color-mix(in srgb, var(--border) 45%, transparent) 10px
  );
  padding: 1.5rem 1rem;
  text-align: center;
  min-height: 7rem;
}
.ph__label {
  font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent);
}
.ph__spec {
  font-family: var(--font-mono);
  font-size: 0.68rem; line-height: 1.6;
  color: var(--text-muted);
  max-width: 44ch;
}
/* Inline marker for a link target that does not exist yet. Deliberately
   not styled as a link, so it cannot be mistaken for a working one. */
.pending {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--text-muted);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 0.1rem 0.4rem;
  white-space: nowrap;
}

.ph--banner  { aspect-ratio: 24 / 10; min-height: 0; }
.ph--wide    { aspect-ratio: 16 / 9;  min-height: 0; }
.ph--icon    { aspect-ratio: 1;  width: 3.5rem; min-height: 0; padding: 0.4rem; }

@media (max-width: 719px) {
  /* Art-directed crop: the mobile banner is a taller frame, not a squashed
     wide one. Swap in Assets/fate-banner-mobile.* at this ratio. */
  .ph--banner { aspect-ratio: 4 / 3; }
}

/* --------------------------------------------------------------------------
   FIGURES: a real image, once an asset has replaced its placeholder box.
   The .ph rules above stay: while assets arrive the pages carry a mix of
   filled and empty slots.
   -------------------------------------------------------------------------- */
.figure {
  margin-inline: 0;                 /* <figure> carries a 40px default */
  margin-block: var(--space-block);
}
.figure a { display: block; }
.figure img {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.figure__caption {
  margin-top: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* A portrait scan left at container width runs past 1600px tall and pushes the
   prose off the screen. Cap the height instead and centre what is left. */
.figure--tall img {
  width: auto;
  max-height: 44rem;
  margin-inline: auto;
}

/* Spreadsheets are only evidence if the numbers can be read. Side by side puts
   a 1600px export at roughly 590px, which is illegible, so the pair stacks at
   full width and each one links to the full-size file. */
.figure-stack {
  display: grid;
  gap: var(--space-block);
  margin-block: var(--space-block);
}

/* --------------------------------------------------------------------------
   13. CASE STUDY PAGES
   -------------------------------------------------------------------------- */
.cs-header { padding-top: clamp(2.5rem, 6vh, 4rem); }
.cs-header__title {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 1.6rem + 3.2vw, 3.75rem);
  font-weight: 700; letter-spacing: -0.03em; line-height: 1;
  color: var(--text-strong);
  margin-bottom: var(--space-block);
}
.cs-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 23rem);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
@media (max-width: 860px) { .cs-split { grid-template-columns: 1fr; } }

.cs-scope {
  font-family: var(--font-mono);
  font-size: 0.78rem; line-height: 1.7;
  color: var(--text);
  border-left: 2px solid var(--accent);
  padding: 0.5rem 0 0.5rem 1rem;
  margin-block: 1.5rem;
  max-width: 60ch;
}

/* Award icon sits beside the case-study title where there is room, and wraps
   beneath it when there isn't. No caption, since the icon carries its own wording,
   so repeating it would say the same thing twice. */
.cs-title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(1rem, 2.5vw, 2rem);
  margin-bottom: var(--space-block);
}
.cs-title-row .cs-header__title { margin-bottom: 0; }

.award-icon {
  flex: 0 0 auto;
  width: clamp(6.5rem, 11vw, 10rem);
  aspect-ratio: 1;
  min-height: 0;
  padding: 0.35rem;
  gap: 0;
  overflow: hidden;
}

/* The same mark on the Somnium card in the work grid, at card scale. Sits
   beside the card title, opposite it, so the row reads title-then-award. */
.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--card-head-h);
}
.award-icon .ph__label { font-size: 0.6rem; letter-spacing: 0.06em; }

/* The real mark is not square, so drop the placeholder's aspect-ratio above and
   let the image keep its own. */
img.award-icon {
  aspect-ratio: auto;
  height: auto;
  padding: 0;
}

/* The card copy is sized by height rather than width, so it matches the title
   band exactly and the width follows from the artwork's ratio. This has to
   outrank img.award-icon above, which sets height:auto, hence the img prefix
   and the position after it. Weakening either puts the mark on screen at its
   natural 1800px. */
img.award-icon--card {
  width: auto;
  height: var(--card-head-h);
}

/* Light mode carries its own artwork rather than a filtered copy of the dark
   one. Both files ship on any page showing the award and the theme picks one:
   that costs a second request, and buys an instant swap on toggle with no
   flash of a missing icon. The hidden one leaves the accessibility tree, so
   the mark is announced once, not twice. */
.award-icon--for-light { display: none; }
:root[data-theme="light"] .award-icon--for-dark  { display: none; }
:root[data-theme="light"] .award-icon--for-light { display: block; }

.cs-nav {
  display: flex; flex-wrap: wrap; gap: 1.5rem; justify-content: space-between;
  border-top: 1px solid var(--border);
  margin-top: var(--space-section);
  padding-top: var(--space-block);
}
.cs-nav a {
  font-family: var(--font-mono);
  font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase;
  text-decoration: none;
}

/* --------------------------------------------------------------------------
   14. EXPERIENCE: prose, no visuals, credibility not showcase
   -------------------------------------------------------------------------- */
.roles { display: grid; gap: var(--space-block); }
.role {
  display: grid;
  grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
  gap: 0.5rem clamp(1.5rem, 4vw, 3rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}
@media (max-width: 720px) { .role { grid-template-columns: 1fr; } }

.role__meta { display: flex; flex-direction: column; gap: 0.3rem; }
.role__studio {
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 500; color: var(--text-strong);
  line-height: 1.2;
}
.role__title, .role__dates {
  font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.06em;
  color: var(--text-muted);
}
.role__body { max-width: var(--measure); }

/* --------------------------------------------------------------------------
   15. TOOLS: load-bearing evidence, not a badge wall
   -------------------------------------------------------------------------- */
.tools { display: grid; gap: 1.5rem; }
.tools__row {
  display: grid;
  grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);  /* same rail as .role */
  gap: 0.4rem clamp(1.5rem, 4vw, 3rem);
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}
@media (max-width: 620px) { .tools__row { grid-template-columns: 1fr; } }
.tools__list {
  font-family: var(--font-mono);
  font-size: 0.82rem; line-height: 1.9;
  color: var(--text);
}

/* --------------------------------------------------------------------------
   16. CONTACT
   -------------------------------------------------------------------------- */
.contact__cta {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.3rem + 2.2vw, 3rem);
  font-weight: 700; letter-spacing: -0.025em; line-height: 1.05;
  color: var(--text-strong);
  margin-bottom: 1.5rem;
}
.contact__primary {
  display: flex; flex-wrap: wrap; gap: 0.75rem 2rem;
  font-size: 1.1rem;
  margin-bottom: var(--space-block);
}
.contact__secondary {
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem; letter-spacing: 0.06em;
  border-top: 1px solid var(--border);
  padding-top: 1.25rem;
}

.footer {
  border-top: 1px solid var(--border);
  padding-block: 2rem 3rem;
  font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.06em;
  color: var(--text-muted);
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; justify-content: space-between;
}

/* --------------------------------------------------------------------------
   17. 404
   -------------------------------------------------------------------------- */
.notfound {
  min-height: 80vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 1.5rem;
}
.notfound__code {
  display: flex; align-items: center; justify-content: center; gap: 0.05em;
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 2.5rem + 15vw, 16rem);
  font-weight: 700; letter-spacing: -0.04em; line-height: 1;
  color: var(--text-strong);
}
/* The 0 is the gauge. */
.notfound__dial {
  position: relative;
  width: 0.82em; height: 0.82em;
  border: 0.11em solid var(--border-strong);
  border-radius: 50%;
  display: inline-grid; place-items: center;
}
.notfound__dial::before {
  content: ""; position: absolute; inset: -0.11em;
  border: 0.11em solid var(--accent);
  border-radius: 50%;
  clip-path: inset(0 0 55% 0);   /* needle arc, overridden by JS */
}
.notfound__needle {
  width: 0.055em; height: 0.3em;
  background: var(--accent);
  transform-origin: 50% 100%;
  transform: translateY(-0.1em) rotate(214deg);
}
.notfound__depth {
  font-family: var(--font-mono);
  font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   18. MOTION: the site is ~90% still by design.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* AMBIENT CRITTERS: deliberately not built in v1. Ege chose to judge the
   fully still version first. When they go in they must: load last, be absent
   on first paint, sit in the chrome layer behind nothing that carries text,
   honour prefers-reduced-motion, and be CSS or lightweight canvas only.
   The reserved layer:
   .critters { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
*/

/* --------------------------------------------------------------------------
   19. PRINT: recruiters do print things
   -------------------------------------------------------------------------- */
@media print {
  .nav, .gauge, .cs-nav, .skip-link, .theme-toggle { display: none; }
  body { background: #fff; color: #000; }
  a { color: #000; }
}
