/*
 * Site styles. All colors and fonts come from tokens.css – change the
 * look there, not here. Layered so later layers win without specificity
 * fights: reset → base → nav → case → work → footer.
 */

@layer reset, base, nav, case, work, footer;

@layer reset {
  * { box-sizing: border-box; }
  html { scroll-behavior: smooth; }
  body { margin: 0; }
  img { display: block; width: 100%; height: 100%; object-fit: cover; }
}

@layer base {
  /* Footer pinned to the viewport bottom on short pages: the body is at least
     one screen tall and the footer takes the leftover space above itself
     (margin-top:auto, footer layer). min-height, not height, so a long page
     grows past it as before; svh is the smallest viewport height, so a
     mobile toolbar can never push a short page into scrolling. */
  body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100svh;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
  }
  /* In a flex column, margin:0 auto shrinks an item to its content instead
     of filling up to its max-width (.case-body, .entry-title, …). Full width
     restores the block behaviour. The skip link is absolutely positioned and
     keeps its own size. */
  body > :not(.skip-link) { width: 100%; }

  h1, h2 { font-family: var(--font-sans); font-weight: var(--weight-heading); text-wrap: balance; margin: 0; }

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

  /* Text selection in the page's accent (site default, or the case's own).
     The accent is owner-picked, so the text colour is derived, not set:
     the accent's WCAG relative luminance, computed in srgb-linear, against
     0.1791 — the point where white and black contrast equally — gives white
     on dark accents and black on light ones, never below 4.58:1. The rule is
     written out here, not as a token on :root, because a custom property
     resolves where it is declared and would miss the inline --accent on
     <body>. Browsers without relative colour syntax keep their default. */
  @supports (color: color(from red srgb-linear r g b)) {
    ::selection {
      background: var(--accent);
      color: color(from var(--accent) srgb-linear
        clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 1e6, 1)
        clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 1e6, 1)
        clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 1e6, 1));
    }
  }

  .eyebrow {
    font-family: var(--font-sans);
    font-weight: var(--weight-label);
    text-transform: uppercase;
    letter-spacing: .14em;
    font-size: .78rem;
    color: var(--stone);
  }

  .skip-link {
    position: absolute;
    left: var(--gutter);
    top: -100%;
    z-index: 100;
    padding: .6rem 1rem;
    background: var(--ink);
    color: var(--paper);
    text-decoration: none;
    font-size: .9rem;
  }
  .skip-link:focus { top: .5rem; }
}

@layer nav {
  .navbar {
    position: sticky;
    top: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Wordmark-to-links spacing: just over a third of the viewport, but never
       more than the row has room for just above the 820px hamburger
       breakpoint (the 100vw - 40rem term leaves the wordmark and a four-link
       menu space). */
    gap: clamp(3rem, 100vw - 40rem, 36vw);
    padding: 1.1rem var(--gutter);
    background: var(--paper);
  }
  .wordmark {
    font-family: var(--font-sans);
    font-weight: var(--weight-heading-strong);
    font-size: 1.3rem;
    letter-spacing: .01em;
    color: var(--ink);
    text-decoration: none;
  }
  .nav-links {
    display: flex;
    align-items: center;
    gap: 2.1rem;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .nav-links a {
    color: var(--ink-soft);
    text-decoration: none;
    font-size: 1.05rem;
    font-weight: var(--weight-ui);
    letter-spacing: .01em;
  }
  /* The page being viewed: darker ink plus an underline, in the text's own
     colour so it turns accent with the rest of the link on hover. */
  .nav-links a[aria-current="page"],
  .mobile-panel a[aria-current="page"] {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: .3em;
  }
  .nav-links a:hover, .nav-links a:focus-visible { color: var(--accent); }

  .hamburger {
    display: none;
    width: 2rem;
    height: 2rem;
    border: 0;
    background: none;
    cursor: pointer;
    padding: 0;
    flex-direction: column;
    justify-content: center;
    gap: .32rem;
  }
  .hamburger span {
    display: block;
    height: 2px;
    width: 100%;
    background: var(--ink);
    transition: transform .2s ease, opacity .2s ease;
  }
  .mobile-panel { display: none; }

  @media (max-width: 820px) {
    .navbar { justify-content: space-between; }
    .nav-links { display: none; }
    .hamburger { display: flex; }
    body.nav-open .mobile-panel {
      display: flex;
      flex-direction: column;
      gap: 0;
      background: var(--paper-raised);
      border-bottom: 1px solid var(--line);
      padding: .5rem var(--gutter) 1.25rem;
    }
    .mobile-panel a {
      padding: .85rem 0;
      border-bottom: 1px solid var(--line);
      text-decoration: none;
      color: var(--ink);
      font-size: 1.02rem;
    }
    body.nav-open .hamburger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
    body.nav-open .hamburger span:nth-child(2) { opacity: 0; }
    body.nav-open .hamburger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
  }
}

@layer case {
  /* ---- hero ---- */
  .hero {
    position: relative;
    /* TODO §7: title/subtitle/year moved below the hero into .entry-title
       (~20vh) — the hero shrinks by the same amount so the page doesn't grow
       taller than before. */
    height: calc(min(88vh, 54rem) - 20vh);
    min-height: 26rem;
    overflow: hidden;
  }
  .hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgb(0 0 0 / .05) 0%, rgb(0 0 0 / 0) 32%, rgb(0 0 0 / .55) 100%);
  }
  /* No hero image: transparent, sized to its own text — not a photo gradient
     over nothing, not the 26rem floor meant to hold a picture, and no
     coloured banner either (the admin sets title_color/accent to black for
     this state — see editor.js — so this only needs to get out of the way). */
  .hero.hero--no-image {
    height: auto;
    min-height: 0;
    background: transparent;
  }
  .hero.hero--no-image::after { content: none; }

  /* ---- title band (TODO §7) ----
     Case title/subtitle/year used to overlay the hero photo as a caption;
     they now sit in their own band below it, left-aligned to the body
     column instead of centered over the image. */
  .entry-title {
    min-height: 10vh;
    display: flex;
    flex-direction: column;
    justify-content: left;
    max-width: var(--measure);
    margin: 0 auto;
    padding: 1.5rem var(--gutter);
    padding-bottom: 0;
    color: var(--ink);
  }
  @media (min-width: 1220px) {
    /* Above this breakpoint .case-body's own gutter sits on the outer 96rem
       box, not on its text column (grid-column:2 has no padding of its
       own) — .entry-title has to match that: drop its horizontal padding
       here too, or the gutter would double up and shift it right of the
       body column it's supposed to align with. */
    .entry-title { max-width: var(--case-measure); padding-inline: 0; }
  }
  .entry-title h1 {
    font-weight: 700;
    font-size: clamp(1.75rem, 4vw, 2.75rem);
    line-height: 1.05;
  }
  .entry-title-year {
    font-style: italic;
    font-weight: var(--weight-heading);
  }
  .entry-title .subtitle {
    font-family: var(--font-sans);
    font-size: 1.14rem;
    line-height: 1.4rem;
    margin-top: .5rem;
    color: var(--ink-soft);
    max-width: 40rem;
  }

  /* Practice (no hero, no title band): title/subtitle/eyebrow sit centered
     on the page's own ground at the old overlay-caption scale. */
  .entry-head h1 {
    /* --title-len (set per entry in render_entry()) is the longest WORD in
       the title, not the whole title — a multi-word title just wraps at the
       huge size (max-width below allows that); a single word that long
       can't wrap, so it has to shrink instead. Short words hit the
       18vw/14rem ceiling exactly as before — the length term only ever
       pulls it down, never up, because clamp() takes the smallest of the
       three above the floor. 0.6 is an approximate average glyph width for
       this font. */
    font-size: clamp(4rem, min(18vw, calc(88vw / (var(--title-len, 8) * 0.6))), 14rem);
    line-height: 1.02;
    margin-top: .3rem;
    max-width: 20ch;
  }
  .entry-head .subtitle {
    font-family: var(--font-sans);
    font-size: 1.14rem;
    line-height: 1rem;
    margin-top: 2.02rem;
    max-width: 40rem;
    color: var(--ink-soft);
  }
  .entry-head .eyebrow {
    font-size: 1.14rem;
    line-height: 1rem;
    margin-top: .35rem;
    color: var(--stone);
  }

  /* A collection with no cover image opens with its title on the page's own
     ground — the same type as a heroless hero caption, without the banner
     machinery that only exists to sit over a photo. */
  .entry-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 3rem var(--gutter) 0;
    color: var(--ink);
  }

  /* ---- body column ----
     Single centered column at --measure. On very wide screens the
     contributors panel is absolutely positioned into the right gutter,
     so it can never stretch the content column's rows. */
  .case-body {
    display: grid;
    grid-template-columns: 1fr;
    max-width: var(--measure);
    margin: 0 auto;
    padding: clamp(2.5rem, 6vw, 4rem) var(--gutter) 6rem;
  }
  /* Home/About/Contact open straight on body text (no hero or title band),
     so they sit a little further below the navbar than a case body does. */
  .page-body { padding-top: clamp(4rem, 9vw, 6.25rem); }
  .case-body > * { grid-column: 1; }

  /* About/Contact's own h1 (TODO §9). Not shown: the page opens straight on
     its body text. It stays in the markup, visually hidden, so the page still
     has its one h1 for screen readers and crawlers (bin/check-site.php no-h1). */
  .page-title {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* ---- contributors ---- */
  .contributors {
    grid-column: 1;
    background: var(--paper);
    border: 1px solid #000;
    margin: 0 0 1.75rem;
  }
  .contrib-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    background: none;
    border: 0;
    font: inherit;
    cursor: pointer;
    padding: 1rem 1.25rem;
    color: var(--ink);
  }
  .contrib-toggle .eyebrow { color: var(--accent); }
  .contrib-toggle svg { width: .6rem; height: .6rem; flex: none; transition: transform .18s ease; }
  .contrib-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
  .contrib-body {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .22s ease;
  }
  .contrib-body > div { overflow: hidden; }
  .contributors.open .contrib-body { grid-template-rows: 1fr; }
  .contrib-inner { padding: 0 1.25rem 1.25rem; display: flex; flex-direction: column; gap: 1.5rem; }
  .contrib-group .eyebrow { margin-bottom: .5rem; }
  .contrib-group p { margin: 0; font-size: .95rem; line-height: 1.6; color: var(--ink-soft); }

  @media (min-width: 1220px) {
    .case-body {
      position: relative;
      /* --case-measure (tokens.css): narrows the body column fluidly near
         the collapse threshold, so the fixed-width contributors sidebar
         always has room without overflow. Shared with .entry-title so both
         center the exact same column, not two formulas that happen to
         agree only below this breakpoint. */
      grid-template-columns: 1fr min(var(--case-measure), 100%) 1fr;
      column-gap: 2.5rem;
      max-width: 96rem;
    }
    .case-body > * { grid-column: 2; }
    /* Above this breakpoint the body is three columns inside 96rem, so a cover
       image spans all three rather than 90vw of a much wider screen. */
    .case-body > .block-image--cover {
      grid-column: 1 / -1;
      width: auto;
      margin-left: 0;
    }
    .contributors {
      grid-column: 3;
      grid-row: 1;
      position: absolute;
      top: 0;
      left: 0;
      /* Exact leftover space in the right-hand grid column: viewport minus
         the body column, minus .case-body's own left+right padding
         (var(--gutter) each side — border-box, so it eats into the grid's
         content box), minus the two column-gaps, halved. Capped at the
         full 18rem sidebar width used once there's room. */
      width: min(18rem, calc((100vw - var(--case-measure) - 2 * var(--gutter) - 5rem) / 2));
      margin: 0;
      border: 0;
    }
    .contrib-toggle { display: none; }
    .contrib-body { display: block; }
    .contrib-inner { padding: 1.5rem; }
  }

  /* ---- content blocks ---- */
  .block { margin: 0 0 clamp(2.5rem, 5vw, 3.5rem); }
  .block:last-child { margin-bottom: 0; }

  /* Set on the block, not only on <p>: text saved outside a paragraph still
     reads at the same size as the paragraphs around it. */
  .block-text {
    font-size: var(--text-body);
    line-height: 1.5;
    color: var(--ink);
  }
  .block-text p {
    font-size: var(--text-body);
    line-height: 1.5;
    color: var(--ink);
    margin: 0 0 1.1rem;
  }
  .block-text p:last-child { margin-bottom: 0; }
  /* Justified text (editor toggle). Hyphenation keeps the stretched word gaps
     small in a narrow column; it follows <html lang="sv">. */
  .block-text--justify {
    text-align: justify;
    -webkit-hyphens: auto;
    hyphens: auto;
  }

  /* Bullet lists and underline come from the editor toolbar; they read as body
     copy, so they inherit the paragraph's size, rhythm and colour. */
  .block-text ul {
    margin: 0 0 1.1rem;
    padding-left: 1.35rem;
    list-style: disc;
  }
  .block-text ul:last-child { margin-bottom: 0; }
  .block-text li {
    font-size: var(--text-body);
    line-height: 1.5;
    color: var(--ink);
    margin-bottom: .35rem;
  }
  .block-text li:last-child { margin-bottom: 0; }
  .block-text li p { margin: 0; }
  .block-text u { text-decoration-thickness: from-font; text-underline-offset: .12em; }

  .block-image img {
    width: 100%;
    max-height: 40rem;
    border: 0;
  }

  /* Cover: the one block that is wider than the text column. The body column
     is centred in the viewport, so 50% of it is the viewport's centre and the
     figure can be pulled out symmetrically. max() keeps it from ever coming
     out narrower than the column it breaks out of — on a phone 90vw is less
     than the column, and there the shift collapses to 0. */
  .block-image--cover {
    width: max(100%, 90vw);
    margin-left: calc(50% - max(50%, 45vw));
  }
  /* Taller cap than a column image, and object-fit so the cap crops the
     letterbox instead of squashing the picture. */
  .block-image--cover img {
    max-height: 90vh;
    object-fit: contain;
  }
  figcaption {
    margin-top: .65rem;
    font-family: var(--font-sans);
    font-size: .82rem;
    letter-spacing: .03em;
    color: var(--ink-soft);
  }

  .block-quote blockquote {
    margin: 0;
    padding-left: 1.6rem;
    border-left: 3px solid var(--accent);
    font-family: var(--font-sans);
    font-weight: var(--weight-heading);
    font-style: italic;
    font-size: clamp(1.4rem, 2.6vw, 1.85rem);
    line-height: 1.4;
    color: var(--ink);
  }
  /* 'small': the quote reads at body-text size (.block-text p) instead of
     the big display size above — everything else about it stays the same. */
  .block-quote--small blockquote {
    font-size: var(--text-body);
    line-height: 1.5;
  }
  .block-quote cite {
    display: block;
    margin-top: .85rem;
    font-style: normal;
    font-family: var(--font-sans);
    letter-spacing: .05em;
    text-transform: uppercase;
    font-size: .8rem;
    color: var(--stone);
  }

  /* Video block: Plyr player fills the column. (The old dashed
     placeholder styling served the static mockup only.) */
  .block-video { width: 100%; }
  .block-video .js-player,
  .block-video video { width: 100%; display: block; }

  /* A plain text link, no box: the underlined title, then the grey host right
     after it. Wraps under the title on a narrow screen rather than overflow. */
  .block-link a {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: .6rem;
    row-gap: .15rem;
    text-decoration: none;
    color: var(--ink);
  }
  .block-link .l-left { display: flex; align-items: center; gap: .5rem; min-width: 0; }
  .block-link .l-icon { width: 1.1rem; height: 1.1rem; flex: none; }
  /* The file block's icon is a label, like the grey extension beside it. */
  .block-link .l-icon--file { color: var(--stone); }
  /* Only the title is underlined; on hover the line (not the text) takes the
     page's accent. */
  .block-link .l-title {
    font-weight: var(--weight-ui);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: .2em;
    text-decoration-color: currentColor;
    transition: text-decoration-color .15s;
  }
  .block-link a:hover .l-title,
  .block-link a:focus-visible .l-title { text-decoration-color: var(--accent); }
  .block-link .l-url {
    font-family: var(--font-sans);
    letter-spacing: .03em;
    color: var(--stone);
    font-size: .85rem;
    white-space: nowrap;
  }
}

@layer work {
  /* /work grid: a contact sheet. Four small landscape thumbnails per row, set
     close together, each carrying its own title. The tiles are the content;
     nothing sits between them. */
  .work-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    align-items: start; /* a short tile never stretches to a tall row */
    gap: clamp(.4rem, .8vw, .75rem);
    /* Top: same distance below the navbar as .page-body (Home/About/Contact).
       Sides: roughly half of About's side margin, never below the gutter. */
    padding: clamp(4rem, 9vw, 6.25rem)
             max(var(--gutter), (100vw - var(--measure)) / 4 + var(--gutter) / 2)
             calc(var(--gutter) * 2);
  }
  @media (max-width: 860px)  { .work-grid { grid-template-columns: repeat(3, 1fr); } }
  @media (max-width: 620px)  { .work-grid { grid-template-columns: repeat(2, 1fr); } }

  /* The Work and Practices overviews' h1. Not shown, like About/Contact's
     .page-title: the page opens straight on the grid / list. Visually hidden,
     not removed, so each page keeps its one h1 for screen readers and
     crawlers (bin/check-site.php no-h1). Absolutely positioned, it takes no
     grid track either. */
  .work-title {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .work-card {
    display: block;
    color: var(--ink);
    text-decoration: none;
  }
  .work-card img {
    width: 100%;
    /* The reset sets height:100%, which in a stretched grid item defeats
       aspect-ratio and lets the image swallow the card. Landscape 3:2 here. */
    height: auto;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    display: block;
  }
  .work-card h2 {
    margin-top: .5rem;
    padding: 0;
    text-align: left;
    font-size: clamp(.85rem, 1vw, 1.05rem);
    font-weight: var(--weight-ui);
    line-height: 1.15;
    transition: color .18s ease;
  }
  .work-card:hover h2,
  .work-card:focus-visible h2 { color: var(--accent); }
  .work-year {
    font-family: var(--font-sans);
    font-weight: 400;
    letter-spacing: .03em;
    color: var(--stone);
    font-size: .85em;
  }
  @media (prefers-reduced-motion: reduce) {
    .work-card h2 { transition: none; }
  }

  /* /practices/ overview: the work grid's sibling. No thumbnails — practices
     have no hero — so the rows carry the whole story: title, and year when
     one is set. */
  .practice-index {
    max-width: var(--measure);
    margin: 0 auto;
    padding: calc(var(--gutter) * 1.5) var(--gutter) calc(var(--gutter) * 2);
  }
  .practice-list { list-style: none; margin: 0; padding: 0; }
  .practice-row a {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 0;
    border-bottom: 1px solid var(--line);
    text-decoration: none;
    color: var(--ink);
  }
  .practice-row a:hover { border-color: var(--accent); }
  .practice-row a:hover .p-title,
  .practice-row a:focus-visible .p-title { color: var(--accent); }
  .p-title {
    font-size: clamp(1.15rem, 2vw, 1.5rem);
    font-weight: var(--weight-ui);
    line-height: 1.15;
  }
  .p-year {
    font-family: var(--font-sans);
    letter-spacing: .03em;
    color: var(--stone);
    font-size: .85rem;
    white-space: nowrap;
  }
}

@layer footer {
  /* "Next" footer switched off (see render_entry in lib/render.php).
  .next-case {
    background: color-mix(in srgb, black 3%, color-mix(in srgb, var(--accent) 8%, var(--paper)));
    padding: clamp(3rem, 7vw, 5rem) var(--gutter);
    text-align: center;
  }
  .next-case a { text-decoration: none; color: inherit; }
  .next-case h2 { font-size: clamp(1.8rem, 4vw, 3rem); margin-top: .6rem; }
  */

  .site-footer {
    margin-top: auto; /* bottom of the viewport on short pages (base: body) */
    padding: 1.5rem var(--gutter) 6rem;
    text-align: center;
    font-size: .85rem;
    color: var(--stone);
  }
  .site-footer a { color: inherit; text-decoration: underline; text-underline-offset: .2em; }
  .site-footer a:hover { color: var(--accent); }
}
