/* ═══════════════════════════════════════════════════════════════════════
   Coastal Legacies — Fables
   Design A, "the strait at depth" (HANDOFF §4).

   Shared by every page in content/fables/. Each page links this file and then
   declares one thing inline: its hero's aspect-ratio.

   Paths resolve from THIS file, not from the pages: Domine lives three levels
   up in app/fonts/, the family's own faces one level up in assets/fonts/.
   ═══════════════════════════════════════════════════════════════════════ */
    /* ═══════════════════════════════════════════════
       Fonts — self-hosted, no external requests.
       Only the weights this page actually renders.
       ═══════════════════════════════════════════════ */
    @font-face {
      font-family: 'Domine';
      font-style: normal;
      font-weight: 700;
      font-display: swap;
      src: url('../../../../fonts/domine-v25-latin/domine-v25-latin-700.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Merriweather';
      font-style: normal;
      font-weight: 400;
      font-display: swap;
      src: url('../fonts/merriweather-v33-latin/merriweather-v33-latin-regular.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-weight: 500;
      font-display: swap;
      src: url('../fonts/montserrat-v31-latin/montserrat-v31-latin-500.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-weight: 600;
      font-display: swap;
      src: url('../fonts/montserrat-v31-latin/montserrat-v31-latin-600.woff2') format('woff2');
    }

    /* ═══════════════════════════════════════════════
       Tokens — Design A, "the strait at depth"
       ═══════════════════════════════════════════════ */
    :root {
      --ink: #0B1A20;          /* the strait at depth */
      --ink-raised: #11262E;   /* raised ground */
      --ink-deep: #071219;     /* outside the page column */
      --sand: #E4E7E2;         /* white sand under northern light */
      --sand-dim: #B9C4C4;     /* running text */
      --tide: #7FA8AE;         /* glacial blue-green — labels, rules */
      --current: #1F9188;      /* house accent */
      --rule: rgba(127, 168, 174, 0.26);
      --rule-soft: rgba(127, 168, 174, 0.14);

      --measure: 36rem;
      --gutter: 24px;

      --display: 'Domine', Georgia, serif;
      --body: 'Merriweather', Georgia, serif;
      --util: 'Montserrat', system-ui, sans-serif;
    }

    *, *::before, *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    html {
      -webkit-text-size-adjust: 100%;
    }

    body {
      background: var(--ink-deep);
      color: var(--sand-dim);
      font-family: var(--body);
      font-size: 17px;
      line-height: 1.78;
      -webkit-font-smoothing: antialiased;
    }

    .page {
      max-width: 1024px;
      margin: 0 auto;
      background: var(--ink);
      overflow: hidden;
    }

    /* ── Language visibility (CSS-only, no flash) ── */
    [data-lang="en"] :is(.lang-fr) { display: none; }
    [data-lang="fr"] :is(.lang-en) { display: none; }

    ::selection {
      background: var(--current);
      color: #fff;
    }

    /* ═══════════════════════════════════════════════
       Masthead
       ═══════════════════════════════════════════════ */
    .masthead {
      position: sticky;
      top: 0;
      z-index: 40;
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 10px var(--gutter);
      padding-top: max(10px, env(safe-area-inset-top, 10px));
      background: rgba(11, 26, 32, 0.86);
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      border-bottom: 1px solid var(--rule-soft);
    }

    .back {
      display: inline-flex;
      align-items: center;
      gap: 7px;
      color: var(--tide);
      text-decoration: none;
      font-family: var(--util);
      font-weight: 600;
      font-size: 10px;
      letter-spacing: 0.16em;
      text-transform: uppercase;
      padding: 6px 2px;
      border-radius: 3px;
      -webkit-tap-highlight-color: transparent;
      transition: color 0.2s;
    }

    .back:hover { color: var(--sand); }

    .back svg {
      width: 13px;
      height: 13px;
      flex-shrink: 0;
    }

    /* ── Language toggle ── */
    .lang-toggle {
      margin-left: auto;
      display: flex;
      align-items: center;
      border: 1px solid var(--rule);
      border-radius: 999px;
      overflow: hidden;
    }

    .lang-toggle button {
      appearance: none;
      background: none;
      border: 0;
      cursor: pointer;
      font-family: var(--util);
      font-weight: 600;
      font-size: 10px;
      letter-spacing: 0.14em;
      color: var(--tide);
      padding: 7px 13px;
      -webkit-tap-highlight-color: transparent;
      transition: background 0.22s, color 0.22s;
    }

    .lang-toggle button[aria-pressed="true"] {
      background: var(--current);
      color: #fff;
    }

    .lang-toggle button:not([aria-pressed="true"]):hover {
      color: var(--sand);
    }

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

    /* ═══════════════════════════════════════════════
       Hero
       Each page declares its own `aspect-ratio` inline —
       that is the one rule which is genuinely per-frame.
       Where the declared ratio IS the frame's intrinsic
       ratio, `cover` removes nothing.
       ═══════════════════════════════════════════════ */
    .hero {
      position: relative;
    }

    .hero img {
      display: block;
      width: 100%;
      /* height:auto is required — the width/height attributes map to
         presentational hints that would otherwise defeat aspect-ratio */
      height: auto;
      object-fit: cover;
    }

    /* Below 700px the natural ratio gives only a ~346px frame, and the title
       block needs most of it — the drawing all but disappears under the veil.
       So narrow screens take the village heroes' `min-height: 60svh` after all,
       trading ~12% off each side (empty snow left, the last houses right) for a
       frame tall enough that the sled and the pallbearers still read. Above
       700px there is height to spare and nothing is cropped. */
    @media (max-width: 699px) {
      .hero img {
        /* 60svh matches the village heroes on a real phone, but on a tall
           narrow window it would crop the drawing to a centre band. Capping
           against the width bounds the crop at ~1.4x the natural height. */
        min-height: min(60svh, 130vw);
      }

      .hero-text {
        padding-top: 56px;
      }
    }

    /* The veil rides on the text block, not on the image.
       The village heroes can scrim a fixed fraction of the frame because their
       photographs are dark at the bottom. This one is bright snow exactly where
       the title sits, and the frame is only 346px tall at 375px wide — a
       percentage-of-image scrim is legible on the desktop hero and useless on
       the phone. Anchoring it to .hero-text means the veil is always exactly as
       tall as the type it has to carry, at every width, and no more of the
       drawing is covered than the words actually need. */
    .hero-text {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 2;
      /* The 96px of top padding is the fade: the ramp finishes before it
         reaches the first line, so every string sits on >=0.90 ground. */
      padding: 96px var(--gutter) 26px;
      background: linear-gradient(
          to top,
          var(--ink) 0%,
          rgba(11, 26, 32, 0.97) 46%,
          rgba(11, 26, 32, 0.90) 66%,
          rgba(11, 26, 32, 0.52) 82%,
          rgba(11, 26, 32, 0.18) 93%,
          rgba(11, 26, 32, 0) 100%
      );
      /* Belt and braces over an illustration whose values shift under the type */
      text-shadow: 0 1px 14px rgba(7, 18, 25, 0.85);
    }

    .eyebrow {
      font-family: var(--util);
      font-weight: 600;
      font-size: 10px;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--tide);
      margin-bottom: 14px;
    }

    .hero h1 {
      font-family: var(--display);
      font-weight: 700;
      font-size: clamp(38px, 10vw, 64px);
      line-height: 1.02;
      letter-spacing: -0.02em;
      color: var(--sand);
      text-wrap: balance;
    }

    .hero .coords {
      margin-top: 14px;
      font-family: var(--util);
      font-weight: 500;
      font-size: 11px;
      letter-spacing: 0.13em;
      color: var(--tide);
    }

    /* ═══════════════════════════════════════════════
       Prose column
       ═══════════════════════════════════════════════ */
    .prose {
      padding: 0 var(--gutter) 64px;
    }

    .prose > * {
      max-width: var(--measure);
      margin-left: auto;
      margin-right: auto;
    }

    .standfirst {
      font-size: 19px;
      line-height: 1.68;
      color: var(--sand);
      padding: 34px 0 6px;
    }

    .prose p + p {
      margin-top: 1.25em;
    }

    /* ═══════════════════════════════════════════════
       The narration
       ═══════════════════════════════════════════════ */
    .listen {
      margin-top: 34px;
      background: var(--ink-raised);
      border: 1px solid var(--rule-soft);
      border-radius: 4px;
      padding: 16px 18px 18px;
    }

    .listen-label {
      font-family: var(--util);
      font-weight: 600;
      font-size: 10px;
      letter-spacing: 0.2em;
      text-transform: uppercase;
      color: var(--tide);
      margin-bottom: 14px;
    }

    .listen-row { display: none; }
    .js .listen-row {
      display: flex;
      align-items: center;
      gap: 16px;
    }

    /* Native player is the ground state: it is what a reader gets when the
       script never runs, or when wavesurfer fails to load. */
    .listen-fallback { width: 100%; display: block; }
    .js .listen-fallback { display: none; }
    .js .listen.no-ws .listen-row { display: none; }
    .js .listen.no-ws .listen-fallback { display: block; }

    .listen-btn {
      appearance: none;
      flex-shrink: 0;
      width: 52px;
      height: 52px;
      border: 0;
      border-radius: 50%;
      background: var(--current);
      display: grid;
      place-items: center;
      cursor: pointer;
      -webkit-tap-highlight-color: transparent;
      transition: filter 0.2s;
    }

    .listen-btn:hover { filter: brightness(1.12); }

    .listen-btn svg {
      width: 19px;
      height: 19px;
      fill: var(--ink);
    }

    /* The glyph follows the state, so only one of the three is ever shown */
    .listen-btn .ico-pause,
    .listen-btn .ico-wait { display: none; }
    .listen.is-playing .listen-btn .ico-play { display: none; }
    .listen.is-playing .listen-btn .ico-pause { display: block; }
    .listen.is-loading .listen-btn .ico-play,
    .listen.is-loading .listen-btn .ico-pause { display: none; }
    .listen.is-loading .listen-btn .ico-wait { display: block; }

    .listen-wave {
      position: relative;
      flex: 1;
      min-width: 0;
      min-height: 52px;
      display: flex;
      align-items: center;
    }

    #waveform { width: 100%; }

    /* Stands in for the waveform until the audio is fetched */
    .listen-bar {
      position: absolute;
      left: 0;
      right: 0;
      height: 2px;
      background: var(--rule);
    }

    .listen.is-ready .listen-bar { display: none; }

    .listen.is-loading .listen-bar {
      animation: listen-pulse 1.1s ease-in-out infinite;
    }

    @keyframes listen-pulse {
      0%, 100% { opacity: 0.32; }
      50% { opacity: 1; }
    }

    .listen-time {
      flex-shrink: 0;
      font-family: var(--util);
      font-weight: 500;
      font-size: 11px;
      letter-spacing: 0.06em;
      color: var(--tide);
      font-variant-numeric: tabular-nums;
    }

    /* On a 320px screen the button and the readout leave the waveform 85px —
       enough to draw, nowhere near enough to scrub. Wrap it onto its own line
       and it gets the full column back. */
    @media (max-width: 420px) {
      .js .listen-row { flex-wrap: wrap; }

      .listen-time { margin-left: auto; }

      .listen-wave {
        order: 3;
        flex-basis: 100%;
        margin-top: 10px;
      }
    }

    /* ═══════════════════════════════════════════════
       The tale — one real heading, and no dates to
       hang on it, so the era rail is absent and the
       section is marked by a short accent rule.
       ═══════════════════════════════════════════════ */
    .tale {
      padding-top: 52px;
    }

    .tale::before {
      content: '';
      display: block;
      width: 36px;
      height: 2px;
      background: var(--current);
      margin-bottom: 20px;
    }

    .tale h2 {
      font-family: var(--display);
      font-weight: 700;
      font-size: clamp(25px, 6.2vw, 36px);
      line-height: 1.16;
      letter-spacing: -0.015em;
      color: var(--sand);
      margin-bottom: 22px;
      text-wrap: balance;
    }

    /* ═══════════════════════════════════════════════
       Plates (full-bleed imagery)
       ═══════════════════════════════════════════════ */
    .plate {
      max-width: none;
      margin: 44px calc(var(--gutter) * -1) 0;
    }

    .plate img {
      display: block;
      width: 100%;
      height: auto;
    }

    .plate figcaption {
      max-width: var(--measure);
      margin: 0 auto;
      padding: 14px var(--gutter) 0;
      font-family: var(--util);
      font-weight: 500;
      font-size: 12.5px;
      line-height: 1.6;
      color: var(--tide);
    }

    /* A plate inside a section still has to clear the paragraph after it */
    .plate + p { margin-top: 44px; }

    /* ── Closing note ── */
    .colophon {
      margin-top: 56px;
      padding-top: 22px;
      border-top: 1px solid var(--rule-soft);
      font-family: var(--util);
      font-weight: 500;
      font-size: 11px;
      line-height: 1.7;
      letter-spacing: 0.06em;
      color: var(--tide);
    }

    /* ═══════════════════════════════════════════════
       Reveal — only engaged when JS is present
       ═══════════════════════════════════════════════ */
    .js-reveal .reveal {
      opacity: 0;
      transform: translateY(14px);
      transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
    }

    .js-reveal .reveal.in {
      opacity: 1;
      transform: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .js-reveal .reveal {
        opacity: 1;
        transform: none;
        transition: none;
      }
      .listen.is-loading .listen-bar { animation: none; opacity: 0.6; }
      * { scroll-behavior: auto !important; }
    }

    /* ═══════════════════════════════════════════════
       Footer nav — matches the rest of the app
       ═══════════════════════════════════════════════ */
    .footer-nav {
      display: flex;
      justify-content: center;
      align-items: center;
      background: #111a1f;
      padding: 6px 0 12px;
      padding-bottom: max(12px, env(safe-area-inset-bottom, 12px));
      border-top: 1px solid rgba(255, 255, 255, 0.06);
    }

    .nav-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 3px;
      padding: 4px 24px;
      cursor: pointer;
      text-decoration: none;
      -webkit-tap-highlight-color: transparent;
    }

    .nav-item svg {
      width: 32px;
      height: 32px;
    }

    /* ═══════════════════════════════════════════════
       Wider screens
       ═══════════════════════════════════════════════ */
    @media (min-width: 700px) {
      :root {
        --gutter: 56px;
      }

      body {
        font-size: 18px;
      }

      .hero-text {
        padding-bottom: 40px;
      }

      .standfirst {
        font-size: 21px;
        padding-top: 46px;
      }

      .listen {
        margin-top: 46px;
        padding: 18px 22px 22px;
      }

      .tale {
        padding-top: 68px;
      }

      .plate figcaption {
        font-size: 13px;
      }
    }

    /* ═══════════════════════════════════════════════
       Archival material
       --ochre is quarantined to archival material (HANDOFF §4). In this family
       it reaches exactly three carriers and nothing else: the .plate--archive
       rule and stamp, the .archival quotation, and the .credit line on the two
       pages whose hero is itself archival. A hero is not a plate, which is why
       that third carrier exists at all — same rule, different carrier.
       ═══════════════════════════════════════════════ */
    :root {
      --ochre: #C08A3E;      /* dried sedge — archival material only */
    }

    /* ── Work titles, vessel names, quoted archival prose ──
       Declared once for the family. Per-page inline CSS followed §3's "declare
       only the weights you use"; a family stylesheet declares what the family
       uses, and italic is load-bearing on two of the four pages. Sharing it
       also removes a footgun: a page adding an <em> can no longer land on a
       synthesised slant. */
    @font-face {
      font-family: 'Merriweather';
      font-style: italic;
      font-weight: 400;
      font-display: swap;
      src: url('../fonts/merriweather-v33-latin/merriweather-v33-latin-italic.woff2') format('woff2');
    }

    .prose em {
      font-style: italic;
      color: var(--sand);
    }

    /* ── Archival hero credit ── */
    .hero .credit {
      margin-top: 12px;
      font-family: var(--util);
      font-weight: 600;
      font-size: 9.5px;
      line-height: 1.6;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--ochre);
    }

    /* ── Archival plates ──
       The stamp carries a year only when the source dates the frame. Egg
       Island's two station photographs are undated, so theirs reads "Archive"
       alone rather than inventing one (§10.5). */
    .plate--archive img {
      filter: contrast(1.04) sepia(0.10);
    }

    .plate--archive figcaption {
      border-left: 2px solid var(--ochre);
      margin-left: var(--gutter);
      margin-right: var(--gutter);
      padding-left: 14px;
      padding-right: 0;
    }

    .plate--archive .stamp {
      display: block;
      font-weight: 600;
      font-size: 9.5px;
      letter-spacing: 0.2em;
      text-transform: uppercase;
      color: var(--ochre);
      margin-bottom: 5px;
    }

    /* ── Quoted archival prose ──
       §10.8's `.archival`, translated from Design B's rust into Design A's
       ochre. Currently carrying the Comeau letter of 1895. */
    .archival {
      margin-top: 46px;
      padding-left: 18px;
      border-left: 2px solid var(--ochre);
      font-style: italic;
    }

    .archival .stamp {
      display: block;
      font-family: var(--util);
      font-style: normal;
      font-weight: 600;
      font-size: 9.5px;
      letter-spacing: 0.2em;
      text-transform: uppercase;
      color: var(--ochre);
      margin-bottom: 18px;
    }

    .archival p + p {
      margin-top: 1.1em;
    }

    .archival .attrib {
      margin-top: 20px;
      font-family: var(--util);
      font-style: normal;
      font-weight: 500;
      font-size: 12px;
      letter-spacing: 0.08em;
      color: var(--tide);
    }

    /* ── A turn in the telling ──
       For a source with no headings, where §10.4 forbids inventing any. Marks
       where the client's own text turns, and carries no words. */
    .turn {
      width: 72px;
      height: 1px;
      background: var(--rule);
      border: 0;
      margin: 44px auto;
    }

    @media (min-width: 700px) {
      .archival {
        padding-left: 24px;
      }
    }
