/* General layout */
html {
  /* Gentle snap so each section settles roughly centered as you scroll,
     without hard-locking the scroll (mandatory snap fought real content). */
  scroll-snap-type: y proximity;
  scroll-behavior: smooth;
}

body {
  font-family: 'Inter', sans-serif;
  margin: 0;
  min-height: 100vh;
  background-color: #121212;
  color: #f0f0f0;
  text-align: center;
}

/* The intro splash (logo + tagline) still gets its own full, centered
   screen; it's just no longer the whole page. */
main {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  scroll-snap-align: center;
}

/* Logo animation */
.myriad-logo {
  max-width: 300px;
  height: auto;
  margin-bottom: 30px;
  animation: logo-zoom 1.6s ease-out forwards;
}

@keyframes logo-zoom {
  0% {
    transform: scale(100);
    opacity: 1;
  }
  40% {
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* Fade-in for text */
.fade-in {
  opacity: 0;
  animation: fade-in 2s ease-in forwards;
  animation-delay: 1s; /* starts after logo zoom */
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Fade-in for text */
.fade-in-first {
  opacity: 0;
  animation: fade-in 2s ease-in forwards;
  animation-delay: 1s; /* starts after logo zoom */
}

@keyframes fade-in-first {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}


/* Fade-in for text */
.fade-in-second {
  opacity: 0;
  animation: fade-in 2s ease-in forwards;
  animation-delay: 4s; /* starts after logo zoom */
}

@keyframes fade-in-second {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Contact info */
.contact-info {
  margin-top: 10px;
  font-family: 'Libre Baskerville', serif;
  color: #e0e0e0;
  line-height: 1.6;
}

.contact-info a {
  color: #00AEEF;
  text-decoration: none;
}

.contact-info a:hover {
  text-decoration: underline;
}

/* Social icons */
.social-icons {
  margin-top: 25px;
}

.social-icon {
  width: 35px;
  height: 35px;
  margin: 0 10px;
  opacity: 0.8;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.social-icon:hover {
  opacity: 1;
  transform: scale(1.1);
}

/* Footer: pinned to the bottom of the viewport at all times, overlaying
   whatever section is currently in view, rather than being scrolled to at
   the end of the page. Translucent + blurred so it reads as a persistent
   bar without fully hiding the content behind it.
   Scoped to `body > footer` (not just `footer`) because the legal pages
   (impressum.html, datenschutz.html) reuse the <footer> tag differently —
   as a small "back to home" link nested *inside* .legal-content, not the
   site-wide bar. That one is a descendant of <main>, not a direct child of
   <body>, so it's untouched by this rule and stays in normal flow. */
body > footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20; /* above .story-foreground (z-index: 5) so it's never covered */
  width: 100%;
  padding: 0.6rem 1rem;
  background: rgba(18, 18, 18, 0.75);
  backdrop-filter: blur(6px);
  text-align: center;
  font-size: 0.85rem;
  color: #888;
  box-sizing: border-box;
}

footer a {
  color: #aaa;
  text-decoration: none;
}

footer a:hover {
  text-decoration: underline;
  color: #fff;
}

body.legal-page {
  background-color: #111;
  color: #f0f0f0;
  font-family: 'Inter', sans-serif;
  margin: 0;
  padding: 0;
  min-height: 100vh;
  overflow-y: auto;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

.legal-content {
  width: 100%;
  max-width: 700px;
  margin: 4rem 1rem;
  padding: 2rem;
  background-color: rgba(255, 255, 255, 0.04);
  border-radius: 12px;
  box-shadow: 0 0 25px rgba(0, 0, 0, 0.4);
  line-height: 1.7;
  text-align: left; /* ✅ Makes paragraphs easy to read */
}

.legal-content h1 {
  text-align: center;
  font-family: 'Libre Baskerville', serif;
  margin-bottom: 2rem;
  letter-spacing: 0.5px;
}

.legal-content p {
  margin-bottom: 1.2rem;
}

.legal-content a {
  color: #00b4ff;
  text-decoration: none;
}

.legal-content a:hover {
  text-decoration: underline;
}

/* ------------------------------------------------------------------
   Scrollytelling section pattern (demo)
   Every "story" section is built from three layers that each move in
   exactly one way:
     - .story-background : fully fixed, never moves at all
     - .story-frame       : scrolls vertically with the page, like normal content
     - .story-foreground  : position: fixed to the true viewport, so it
                             NEVER moves vertically either — the only
                             transform it ever gets is horizontal translation,
                             faded in/out as its section passes through view
   See ./agent/2026-08-16-scrollytelling-section-pattern.md for the
   reasoning behind this approach.
   ------------------------------------------------------------------ */

.story-section {
  position: relative;
  height: 88vh; /* shorter than the viewport so neighbors peek in above/below */
  margin-block: 6vh;
  /* Clips the background/frame to this section's own box if their content
     ever overflows it. Doesn't affect .story-foreground below, since that's
     position: fixed and escapes it on purpose. */
  overflow: clip;
  isolation: isolate; /* keep this section's stacking context self-contained */
  scroll-snap-align: center;
}

.story-background {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(160deg, #1b1b2f 0%, #2c2c54 50%, #1b1b2f 100%);
  background-attachment: fixed; /* never moves, not even while the page scrolls */
  background-size: cover;
  background-position: center;
}

/* Per-section background images: add one small modifier rule per image and
   apply it alongside .story-background in the HTML (class="story-background
   story-background--whatever"). Only background-image needs setting here —
   attachment/size/position are already handled by .story-background above. */

/* Per-section background VIDEO: nest a <video> inside .story-background
   (see index.html) rather than using background-image — background-image
   only accepts image formats, not video, regardless of what a given
   browser might appear to do with a video URL there. Unlike an image
   background, this can't use background-attachment: fixed (that's an
   image-only property), so it scrolls with its section rather than
   staying visually static — a real trade-off, not a bug. */
.story-background video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Normal in-flow content: scrolls vertically with the page like any other
   element, moving out of view as the user scrolls past it. */
.story-frame {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 1rem;
  padding: 4vh 6vw;
  box-sizing: border-box;
  /* Overrides the centered text-align inherited from body — kicker, title
     and body text all pick this up without needing it set individually. */
  text-align: left;
}

/* Reserves whatever vertical space is left in the frame below the text —
   flex: 1 1 auto claims the remainder of .story-frame's height
   automatically, so it (and therefore .story-foreground, sized from it —
   see below) grows/shrinks with the FRAME's height, not with viewport
   width. Empty/invisible; scroll-pattern.js only reads its geometry. */
.story-items-slot {
  flex: 1 1 auto;
  min-height: 0;
}

.story-title {
  font-family: 'Libre Baskerville', serif;
  font-size: clamp(2rem, 5vw, 3.5rem);
  margin: 0;
  /* -webkit-text-stroke (despite the prefix, supported in Firefox/Safari/
     Chrome/Edge alike today) draws a real outline around each glyph — but
     it straddles the glyph's own outline (half inside, half outside), so
     at 3px stroke width, only ~1.5px ends up visible outside the letter.
     paint-order: stroke fill paints the stroke FIRST and the fill on top
     of it, covering the inner half — leaving a clean, uniform-width
     outline entirely outside the original letterform instead of one that
     eats into it. */
  -webkit-text-stroke: 10px black;
  paint-order: stroke fill;
}

/* Fallback for the rare browser without -webkit-text-stroke/paint-order
   support: stacked text-shadows in 8 directions (4 cardinal + 4 diagonal)
   approximate a uniform outline — these are separate offset copies behind
   the fill, not a centered stroke, so they're already outside-only without
   needing paint-order. */
@supports not (-webkit-text-stroke: 3px darkgreen) {
  .story-title {
    text-shadow:
      1.5px 0 0 darkgreen,
      -1.5px 0 0 darkgreen,
      0 1.5px 0 darkgreen,
      0 -1.5px 0 darkgreen,
      1.5px 1.5px 0 darkgreen,
      -1.5px 1.5px 0 darkgreen,
      1.5px -1.5px 0 darkgreen,
      -1.5px -1.5px 0 darkgreen;
  }
}

.story-kicker {
  font-family: 'Inter', sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.75rem;
  color: #f0a500;
  margin: 0;
}

/* Fixed to the viewport (not the section, not the document) so it has zero
   vertical motion under any circumstance — no scroll, no entry/exit drift.
   Its top/left/width/height come from --slot-* custom properties, computed
   in JS (assets/scroll-pattern.js) from .story-items-slot's geometry, so
   this layer sits exactly "inside the frame, under the text" and is sized
   by the FRAME's available height rather than viewport width. Critically,
   --slot-top is NOT the slot's live (scrolling) position — that would
   reintroduce vertical motion — it's computed from where the slot would
   sit once the section settles into its centered resting position, which
   is scroll-invariant. See the comment in scroll-pattern.js for the math.

   Its entrance is triggered by comparing TWO elements' positions (the
   frame's top edge vs. a fixed point near the top of the viewport) — a CSS
   scroll-timeline can only measure its own subject crossing the viewport,
   not another element's position, so that comparison is computed in JS and
   handed to this layer as the --story-progress custom property (0 = not
   yet triggered, 1 = fully panned/exited). CSS still owns the actual
   visual transform/fade. */
.story-foreground {
  position: fixed;
  top: var(--slot-top, 50vh);
  left: var(--slot-left, 0px);
  width: var(--slot-width, 100vw);
  height: var(--slot-height, 50vh);
  z-index: 5;
  box-sizing: border-box;
  overflow: hidden; /* safety clip if rows can't quite fit the slot's height */
  display: flex;
  flex-direction: column; /* stack of rows, not a single side-scrolling row */
  gap: 1.5rem;
  pointer-events: none; /* don't block clicks while faded out elsewhere on the page — real links opt back in below */
  /* --story-progress drives the slide across the whole journey;
     --story-opacity is a separate fade-in/hold/fade-out envelope over that
     same journey (both computed together in JS — see scroll-pattern.js).
     progress 0   -> translateX(+100%): fully off-screen right (of the slot)
     progress 0.5 -> translateX(0):     flush, fully on screen
     progress 1   -> translateX(-100%): fully off-screen left (of the slot)
     i.e. a continuous right-to-left slide-through, not a slide-in-and-stop —
     it keeps moving left past the flush point as scrolling continues. */
  opacity: var(--story-opacity, 0);
  transform: translateX(calc((1 - 2 * var(--story-progress, 0)) * 100%));
}

/* One story-item = one row = one image + one story-panel, side by side.
   Multiple story-items stack vertically inside .story-foreground (which is
   itself the thing that slides horizontally as a whole — see above).
   Grid rather than flex for the row itself because it's a genuinely
   two-column layout (fixed-ish image column, flexible text column) — flex
   would need the same grow/shrink juggling grid gives for free via
   `auto 1fr`.
   The image is optional: with no .story-item-image present, .story-panel
   spans both columns (its default below) via :has(), so a text-only row
   still reads as one full-width card instead of leaving a gap.
   Which side the image sits on is just which column it's placed in —
   .story-item--reverse swaps image and panel to opposite columns, so any
   individual row can have its image on the left (default) or right. */
.story-item {
  /* Rows share .story-foreground's fixed height evenly (flex-basis 0 = pure
     proportional split), rather than each sizing itself from its own
     content and potentially overflowing the available space — this is the
     "height informed by the frame, not by content/width" part. min-height:
     0 lets a row shrink below its content's natural size instead of
     forcing the whole stack taller than the slot. */
  flex: 1 1 0;
  min-height: 0;
  /* Safety net, not the primary fix: .story-panel's font-size/padding below
     are sized in cqh (relative to THIS element's own height, via
     container-type: size just below), so content should actually shrink to
     fit the row rather than needing to be clipped. This just catches
     whatever slips through that (e.g. very long, unbroken text) — without
     it, a row whose content still wants more height than its flex share
     could grow past its allotted slice and visually spill into the row
     below, overlapping it and covering the panel's rounded corners with the
     next row's straight edge. */
  overflow: hidden;
  /* Matches .story-panel's own radius: if the panel's box ever ends up
     even slightly larger than this row (the exact cause has been hard to
     pin down without live layout inspection), clipping it against a
     SQUARE boundary produces a flat cut where a rounded corner should be.
     Clipping against a boundary with the same radius means whatever gets
     clipped still reads as a clean rounded card either way. */
  border-radius: 12px;
  display: grid;
  /* fit-content(45%), not plain auto: sizes the image column to the
     image's own rendered (max-content) width — see .story-item-image's
     width: auto below — but caps it at 45% of the row, so a wide/
     panoramic image can't squeeze the panel down to nothing. (Originally
     shipped uncapped — no image was extreme enough to need it at the
     time — but a wide image doing exactly that is what prompted adding
     this cap.) 1fr on the panel's track still claims whatever's left
     after the (now-capped) image column and the gap. fr, not %, for the
     panel track for the same reason documented before: percentages don't
     account for gap and can overflow the row by the gap's width. */
  grid-template-columns: fit-content(45%) 1fr;
  /* stretch: makes the image's own box match the row's (now height-driven,
     not content-driven) height exactly. */
  align-items: stretch;
  gap: 1.5rem;
}

/* container-type: size is scoped to desktop/tablet only, rather than being
   declared unconditionally and then cancelled again in the mobile media
   query below — .story-item no longer has a fixed shared height on mobile
   (flex: 0 0 auto, content-sized, not flex: 1 1 0), so there's nothing
   for size containment to meaningfully contain there; only ever declaring
   it here removes any dependency on an override reliably cancelling it. */
@media (min-width: 769px) {
  .story-item {
    /* Establishes this element as a query container so .story-panel's cqh
       units resolve against ITS height — i.e. against the row's actual
       available space, not the viewport. */
    container-type: size;
  }
}

.story-item--reverse {
  grid-template-columns: 1fr fit-content(45%);
}

/* Smaller portrait images (e.g. the Team section) — now a height cap
   rather than a width fraction, since width is content-driven (above). A
   shorter image computes a narrower auto width too, so the panel absorbs
   the freed space automatically. align-self: center is needed because
   align-items: stretch (the row's default) only stretches items whose
   cross size is auto; an explicit height here makes it degrade to
   top-aligned unless overridden. */
.story-item--small-image .story-item-image {
  height: 55%;
  align-self: center;
}

.story-item-image {
  grid-column: 1;
  /* width: 100% (not auto): matches its grid column exactly, whatever
     .story-item's fit-content(45%) computed that to be. width: auto
     relies on the browser computing a used width from the image's own
     aspect ratio × the height below — usually matches what fit-content()
     allocated, but not always: on a narrow/tall viewport (a short window
     width with a viewport-height-driven row height, e.g. index.html's
     Paragon's Hand section resized narrow), the computed width can
     exceed the actual column, visibly overlapping the panel next to it.
     object-fit: contain (below) still shows the whole image, just
     letterboxed within this now-guaranteed-to-fit box instead of
     cropped — narrower images are unaffected either way, since
     fit-content(45%) already sizes the column down to their max-content
     width when that's under 45%. */
  width: 100%;
  height: 100%; /* stretched to match the panel's height (see align-items: stretch above) */
  /* Grid/flex items default to min-width/min-height: auto, which for a
     replaced element like <img> resolves to its OWN intrinsic size as a
     floor — the image can refuse to shrink below its natural dimensions
     inside its cell. Browsers have historically differed on how strictly
     this applies; without overriding it to 0, the box can end up sized by
     the image's own aspect ratio rather than the grid column, leaving
     object-fit: contain less room to work with and effectively cropping
     the image instead of scaling it down to fit. */
  min-width: 0;
  min-height: 0;
  object-fit: contain;
  object-position: left center;
  border-radius: 12px; /* matches .story-panel's corner radius */
  display: block;
}

.story-item--reverse .story-item-image {
  grid-column: 2;
}

.story-panel {
  grid-column: 1 / -1; /* spans the full row by default (no image sibling) */
  min-width: 0;
  /* Explicit, not just the default align-items: stretch — matches
     .story-item-image's own explicit width/height: 100% below. Relying on
     implicit stretch alone here (while the parent .story-item has
     container-type: size) let the panel's actual box grow slightly past
     its row's clip boundary on the right/bottom, cutting the rounded
     corners off there while the top-left (nowhere near that boundary)
     rendered fine — an inconsistency only visible on close inspection. */
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  overflow: hidden; /* safety net, see the comment on .story-item's overflow above */
  background: rgba(0, 0, 0, 0.56);
  border: 0px solid rgba(255, 255, 255, 0.32);
  border-radius: 12px;
  /* cqh = 1% of .story-item's own height (its container-type: size above) —
     padding shrinks as the row gets shorter (more rows, a wider/shorter
     window) instead of staying fixed and eating into the space text needs.
     Bumped up from clamp(0.75rem, 6cqh, 1.5rem): text was landing right at
     (sometimes past) the right edge with the tighter clamp. */
  padding: clamp(1rem, 7cqh, 1.75rem);
  backdrop-filter: blur(8px);
  text-align: left;
}

.story-item:has(.story-item-image) .story-panel {
  grid-column: 2; /* sits beside the image instead of spanning */
}

.story-item--reverse:has(.story-item-image) .story-panel {
  grid-column: 1;
}

/* Defensive fallback: if an image ever ends up nested directly inside a
   .story-panel instead of as a .story-item-image sibling, keep it from
   blowing up the panel's size the way the unconstrained one did. */
.story-panel img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}

.story-panel h3 {
  font-family: 'Libre Baskerville', serif;
  font-size: clamp(0.95rem, 8cqh, 1.4rem); /* cqh: see .story-panel's padding comment above */
  margin: 0 0 clamp(0.2rem, 2cqh, 0.5rem);
}

/* Browser default paragraph margins (~1em top+bottom each) add up fast in
   panels with several short lines (e.g. name/role/bio), which is what
   inflated the Team section's row height enough to break the entrance
   animation's geometry (see scroll-pattern.js's "degenerate case"). */
.story-panel p {
  font-size: clamp(0.75rem, 6cqh, 1rem); /* cqh: see .story-panel's padding comment above */
  margin: 0 0 clamp(0.2rem, 1.5cqh, 0.5rem);
}

.story-panel p:last-child {
  margin-bottom: 0;
}

/* Any real link inside a panel (text links and icon links alike) needs to
   opt back into pointer-events, since .story-foreground sets
   pointer-events: none on itself so it doesn't block clicks on other page
   content while off-screen/fading — that would otherwise make every link
   inside it unclickable too, even while fully visible. */
.story-panel a {
  pointer-events: auto;
}

/* Text links inside a panel (e.g. "Discover Paragon's Hand →") — reuses the
   kicker's accent color rather than introducing a third link color. */
.story-panel-link {
  color: #f0a500;
  font-weight: 600;
  text-decoration: none;
}

.story-panel-link:hover {
  text-decoration: underline;
}

/* ------------------------------------------------------------------
   Mobile/small-screen layout.
   The fixed 88vh section height and the fixed-position sliding
   .story-foreground both assume there's enough WIDTH for a side-by-side
   image+text row and enough HEIGHT for a screen's worth of content.
   Neither holds on narrow screens: the panel column gets squeezed too
   narrow for its text to fit the row's fixed share of the section's
   height, cutting it off.
   Below this breakpoint: sections are allowed to grow taller than the
   screen (height: auto, sized by content, instead of a fixed 88vh), and
   .story-foreground drops out of position: fixed back into normal
   document flow — no horizontal slide, no JS-computed position/size —
   so rows just stack top to bottom under the text like a traditional
   page. scroll-pattern.js keeps running unmodified; every property its
   custom properties fed into the desktop version is overridden below
   with a plain static value instead, so its output is simply unused here.
   Desktop/tablet above this breakpoint is untouched.
   ------------------------------------------------------------------ */
@media (max-width: 768px) {
  .story-section {
    height: auto; /* was a fixed 88vh */
    /* was 6vh, sized specifically for the "peek at the next section"
       effect, which doesn't apply once a section can be arbitrarily
       tall — a small fixed gap for visual separation instead. */
    margin-block: 2rem;
    /* Snapping a section far taller than the viewport to "centered"
       fights normal reading scroll rather than helping it. */
    scroll-snap-align: none;
  }

  .story-frame {
    height: auto; /* was 100% of the section's own (now auto) height */
  }

  .story-items-slot {
    display: none; /* existed only as a JS measurement anchor for the fixed-position .story-foreground below, which is disabled at this width */
  }

  .story-foreground {
    /* Back into normal flow: just a block sitting below .story-frame's
       text, stacking its rows top to bottom.
       position: relative (not static!) + z-index: 1 is the actual fix for
       the "images invisible, panel text fine" bug: .story-background's
       video is position: absolute; z-index: 0, painting above any plain
       (non-stacking-context) in-flow content. .story-panel happens to
       create its own stacking context via backdrop-filter (a property
       that does this even on a position: static element), so panel text
       was accidentally painting above the video — but .story-item-image,
       a plain <img> with no such property, was staying as ordinary
       in-flow content and painting BEHIND the video, fully rendered
       (confirmed nonzero size in dev tools) but never visible. On
       desktop this never surfaced because .story-foreground itself is
       position: fixed; z-index: 5, which promotes everything inside it,
       images included; static here removed that umbrella promotion.
       relative (not static) keeps normal-flow layout in principle — but
       CRITICALLY, top/left must be reset here too: the desktop rule sets
       top: var(--slot-top, ...) / left: var(--slot-left, ...), values
       JS recomputes every scroll frame as an absolute viewport
       coordinate meant for position: fixed. Those are silently ignored
       under position: static (top/left have no effect there) but DO
       apply as real offsets once the element is position: relative —
       without resetting them, the element gets shoved to a
       constantly-recalculated position every scroll frame, which reads
       as "stuck"/not scrolling normally rather than the intended
       in-flow behavior. */
    position: relative !important;
    top: auto !important;
    left: auto !important;
    z-index: 1;
    width: auto;
    height: auto;
    overflow: visible;
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto;
    /* Matches .story-frame's own horizontal padding, so rows line up
       under the text above them. */
    padding: 0 6vw 2rem;
    box-sizing: border-box;
  }

  /* Stacked (image above, panel below) instead of side-by-side grid
     columns — a fixed two-column layout is what was squeezing panel text
     into too little width. Row height is no longer shared/fixed
     (flex: 0 0 auto, not 1 1 0) — .story-panel's font-size/padding switch
     from cqh units back to fixed rem values below because container-type:
     size (needed for cqh to mean anything) is now only ever declared for
     desktop/tablet in the first place (see the @media (min-width: 769px)
     block above .story-item--reverse). */
  .story-item {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    min-height: 0;
    overflow: visible;
    gap: 1rem;
  }

  .story-item-image {
    width: 100%;
    height: auto; /* intrinsic aspect ratio from width alone; no letterboxing to manage */
    /* Explicit, not just relying on DOM order (image already comes before
       .story-panel in the markup, so this is currently a no-op) — this way
       the image is always guaranteed to stack above the panel here even
       for a future .story-item--reverse row, where the image sits AFTER
       the panel in the grid (for the desktop "image on the right" layout)
       but should still go on top once stacked on mobile. */
    order: -1;
  }

  /* Team portraits: was a height cap (55% of a fixed row height) that
     doesn't apply once row height is content-driven — a definite width
     instead, centered, so a small portrait doesn't stretch to the full
     row width the way the larger illustration images do. A definite
     width (not auto capped by max-width) mirrors the same pattern that
     already works for the larger images above (width: 100%) — just a
     fixed 160px instead of 100%, rather than relying on width: auto's
     intrinsic-size-then-cap behavior for a replaced element inside a
     column flex context. */
  .story-item--small-image .story-item-image {
    width: 160px;
    max-width: 100%; /* safety net on very narrow screens */
    height: auto;
    align-self: center;
  }

  .story-panel {
    width: 100%;
    height: auto; /* was 100%, matching a fixed row height that no longer exists */
    padding: 1.25rem;
  }

  .story-panel h3 {
    font-size: 1.15rem;
  }

  .story-panel p {
    font-size: 0.95rem;
  }
}