/* ===========================================================================
   THE ROOM HERO.  One definition, every room (Rob, 2026-09-29).
   ---------------------------------------------------------------------------
   A room opts in with ONE line, before the header include -- the order matters,
   because _header.html is what stamps the attribute and Jinja reads a {% set %}
   in document order:

       {% set room_hero = 'lantern' %}
       {% include '_header.html' %}

   _header.html asks hero_url() whether /static/hero/<name>.webp actually exists.
   IF THE FILE IS ABSENT NOTHING IS STAMPED, so there is no data-hero, no rule
   matches, and no request is made -- a room can be wired for a hero it has not
   been given yet and look exactly as it does today. That is how /iching ships
   in this fence: hooked, imageless, and proof the definition is shared rather
   than Lantern-shaped.

   The image arrives as a custom property, not as a selector here, so a room's
   art is data and this file is geometry. A dark-specific file later is a rule
   change, not a rewrite: drop <name>-dark.webp beside it and hero_url picks it
   up as --hero-img-dark, which the dark block below already prefers.

   NO <img>. The hero is decoration -- there is nothing for a screen reader to
   skip and no alt text to invent for nine rooms.
   =========================================================================== */

/* THE GROUND MOVES TO html ON HERO PAGES, and this is the one thing a room has
   to know. A ::before at z-index:-1 paints above html's background and below
   body's content -- but BELOW body's own background, and body is where this house
   paints var(--bg). So a hero page makes body transparent and lets html hold the
   ground. !important because a page's own <style> loads after this sheet and
   would otherwise win on equal specificity, the same cascade law header.css
   already invokes for body padding.
   A ROOM WITH ITS OWN BODY BACKGROUND (card_public's radial gradient, say) must
   move that to html before it can carry a hero. None does today. */
html{ background:var(--bg); }
body[data-hero]{ background:transparent !important; position:relative; }

body[data-hero]::before{
  content:'';
  position:absolute;
  z-index:-1;
  pointer-events:none;
  background-image:var(--hero-img);
  background-repeat:no-repeat;
  background-position:top right;
  background-size:cover;

  /* THE FADE IS A MASK, not a gradient painted over the art. Masking to
     transparency means the page ground shows through whatever it happens to be,
     so the fade needs no per-theme rule and would still be right if a third
     theme ever arrived. One radial from the top-right corner rather than two
     composited linears: mask-composite is where Safari and Chrome disagree, and
     a corner fade is what a corner-set image wants anyway. */
  -webkit-mask-image:radial-gradient(125% 125% at 100% 0%,
      #000 30%, rgba(0,0,0,.55) 62%, transparent 86%);
          mask-image:radial-gradient(125% 125% at 100% 0%,
      #000 30%, rgba(0,0,0,.55) 62%, transparent 86%);

  opacity:var(--hero-opacity, .92);
  filter:var(--hero-filter, none);
  transition:opacity .2s ease;
}

/* ---- widths (Rob's ruling) ------------------------------------------------
   >=820 top-right ~320px · 620-819 ~240px · <=619 behind the title, reduced.
   Written mobile-first so the narrow case is the default and cannot be missed
   by a breakpoint that fails to match. */

/* <=619: BEHIND THE TITLE. Not shrunk -- a 90px landscape is illegible -- and
   not cropped, because the subject is the lantern and the mountains are what
   make it a landscape. Full width, top, fading down, and dimmer so the date and
   the title stay the thing being read (§6: if a traveller must read it, it is
   var(--text) at full strength, and nothing may compete with that). */
body[data-hero]::before{
  top:0; right:0; left:0;
  height:300px;
  background-position:top center;
  --hero-opacity:.34;
  -webkit-mask-image:linear-gradient(to bottom,
      #000 0%, rgba(0,0,0,.5) 55%, transparent 100%);
          mask-image:linear-gradient(to bottom,
      #000 0%, rgba(0,0,0,.5) 55%, transparent 100%);
}

@media (min-width:620px){
  body[data-hero]::before{
    left:auto; width:240px; height:240px;
    background-position:top right;
    --hero-opacity:.92;
    -webkit-mask-image:radial-gradient(125% 125% at 100% 0%,
        #000 30%, rgba(0,0,0,.55) 62%, transparent 86%);
            mask-image:radial-gradient(125% 125% at 100% 0%,
        #000 30%, rgba(0,0,0,.55) 62%, transparent 86%);
  }
}
@media (min-width:820px){
  body[data-hero]::before{ width:320px; height:320px; }
}

/* ---- dark theme ----------------------------------------------------------
   The MASK needs no dark variant; the IMAGE does. A glowing lantern in a bright
   mountain landscape is a high-luminance rectangle, and masked onto #1a1714 it
   reads as a hole in the page rather than a mood. Dimmed and darkened here as
   Rob specified (brightness .72, opacity .55), and tunable by these two numbers
   alone. When a purpose-made dark file lands, --hero-img-dark takes over and
   these can go back to 1 / .9 -- which is why the file is preferred here rather
   than the filter being the only answer. */
html[data-theme="dark"] body[data-hero]::before{
  background-image:var(--hero-img-dark, var(--hero-img));
  --hero-filter:brightness(.72) saturate(.92);
  --hero-opacity:.55;
}
@media (max-width:619px){
  html[data-theme="dark"] body[data-hero]::before{ --hero-opacity:.26; }
}

@media (prefers-reduced-motion:reduce){
  body[data-hero]::before{ transition:none; }
}
